Forum Discussion

Faintly_Lucky's avatar
Faintly_Lucky
Icon for Nimbostratus rankNimbostratus
Mar 17, 2011

iRule not triggered on target VIP after using the virtual iRule command to direct traffic to it

My company has a pair of 1600s (9.4.8 HF4) that accept and load balance all of the syslog traffic generated by our devices to several syslog pools.

 

 

Recently, we had a requirement come down to pass access-control messages from the TACACS servers for a certain subset of devices to a different, dedicated pool.

 

 

So, I wrote up a rule on the main syslog VIP that switched on the addresses of the TACACS servers and pushed them to a secondary VIP that I created specifically to handle the traffic.

 

 

I wrote another rule that matched the addresses of the pertinent devices in the UDP payload and selected the proper pool for them and applied it to the secondary VIP, then implemented the rule on the main VIP.

 

 

The rule on the main VIP acted like it should:

 

 

Mar 16 13:48:53 tmm tmm[1706]: Rule syslog-pool-select-v4 : Sending traffic to other virtual as expected

 

Mar 16 13:48:53 tmm tmm[1706]: Rule syslog-pool-select-v4 : Sending traffic to other virtual as expected

 

Mar 16 13:48:54 tmm tmm[1706]: Rule syslog-pool-select-v4 : Sending traffic to other virtual as expected

 

Mar 16 13:49:13 tmm tmm[1706]: Rule syslog-pool-select-v4 : Sending traffic to other virtual as expected

 

 

The secondary VIP rule never logged anything and when I checked the statistics, they were zeroed like the rule wasn't being triggered even though I confirmed that it was applied to the secondary VIP.

 

 

Any Ideas?

 

 

Thanks in advance,

 

 

Lucky

 

 

 

 

Main Syslog VIP

 

 

rule syslog-pool-select-v4 {

 

when CLIENT_ACCEPTED {

 

set addr [IP::client_addr]

 

switch $addr {

 

xxx.xxx.xxx.xxx -

 

xxx.xxx.xxx.xxx { virtual seim-syslog-tacacs

 

log local0.info "Sending traffic to other virtual as expected" }

 

}

 

if { [matchclass $addr starts_with $::syslog_chan1_string] }

 

{ pool syslog_pool_Channel_1 }

 

elseif { [matchclass $addr starts_with $::syslog_chan2_string] }

 

{ pool syslog_pool_Channel_2 }

 

else { pool syslog_pool_Channel_0 }

 

}

 

}

 

 

Secondary Syslog VIP

 

 

rule syslog-tacacs-pool-select {

 

when CLIENT_DATA {

 

set addr [findstr [UDP::payload] Address 8 ,]

 

if { [matchclass $addr equals $::XXXXX_subnets_network] } { pool syslog_pool_XXXXXX

 

log local0.info "I selected the XXXXX pool, YAY!.....addr $sddr" }

 

else { pool syslog_pool_Channel_1

 

log local0.info "selected syslog channel 1" }

 

}

 

}

 

 

  • I'd really appreciate it if someone could give me some ideas on this or explain what's happening.

     

     

    I've continued to troubleshoot this after posting and I'm still not having any luck.

     

     

    Thanks,

     

    Lucky
  • Hi Lucky,

     

     

    Can you post an anonymized copy of your virtual server definitions using 'b virtual VS_NAME list'?

     

     

    Thanks, Aaron
  • Sure can, but all that typing gets to you eventually. I started using aliased commands and functions a long time ago :)

     

     

    VIP Defs below. Also another anonymized copy of the secondary rule as I made some changes to it troubleshooting to see if they had any effect.

     

     

    From the troubleshooting that I've done so far, it would appear that the pool selection commands in the primary rule that come after the virtual command are overriding the VIP selection as the secondary virtual is zeroed out on stats.

     

     

    Thanks for taking a look at this.

     

     

    Lucky

     

     

    [root@XXXXXX:Active] config bv list

     

    virtual SEIM_SYSLOG_VIP {

     

    destination xxx.xxx.xxx.xxx:shell

     

    ip protocol udp

     

    rules syslog-pool-select-v4

     

    }

     

    virtual seim-syslog-tacacs {

     

    pool syslog_pool_Channel_1

     

    destination xxx.xxx.xxx.xxx:shell

     

    ip protocol udp

     

    rules syslog-tacacs-pool-select

     

    profiles udp-test

     

    }

     

     

    [root@xxxxxxx:Active] config bpr udp list

     

    profile udp udp {

     

    idle timeout 60

     

    }

     

    profile udp udp-test {

     

    defaults from udp

     

    datagram lb enable

     

    }

     

     

     

    [root@xxxxxx:Active] config br syslog-tacacs-pool-select list

     

    rule syslog-tacacs-pool-select {

     

    when LB_SELECTED {

     

    set addr [findstr [UDP::payload] Address 8 ,]

     

    if { [matchclass $addr starts_with $::xxxxxxsubnetstring] } { LB::reselect pool syslog_pool_xxxxxxx

     

    log local0.info "I selected the xxxxxxx pool, YAY!.....addr $sddr" }

     

    else { log local0.info "selected syslog channel 1" }

     

    }

     

    }

     

     

  • I don't see anything obviously wrong with the iRule. I haven't tested the virtual command with UDP before though. Can you try a simplified test with an iRule that just calls the second virtual server for all connections and see if that works to start with?

     

     

    You might also try opening a case with F5 Support on this.

     

     

    Aaron
  • spark_86682's avatar
    spark_86682
    Historic F5 Account
    The problem is in your syslog-pool-select-v4 iRule. Although your switch statement will set the destination to the virtual, your else statement at the bottom will send it to the syslog_pool_Channel_0 pool instead, essentially overriding the earlier "virtual" statement. In your case, you need to make sure that you don't call a "pool" command if you've already called "virtual". There are a couple ways of doing that; the easiest might be to do a "return" after calling your log statement.

     

  • Hi Spark,

     

     

    Thanks for catching that. I didn't notice the second pool command were hitting for all cases.

     

     

    Aaron
  • Spark/Aaron:

    I figured out the pool selection issue last week and corrected it, though why the virtual command is able to be overridden by a later pool command has me scratching my head.

    Thanks for mentioning the return command. I use it regularly in rules, but I guess that I got caught up in the weirdness of the catch-all pool command overriding the virtual command and didn't think about it. I just eliminated the catch-all and assigned it as the VIP's default pool.

    I still have a problem though. Aaron, I took your advice and opened a case with F5 on this. I'm sorry to say it, but any progress that I've made on this issue has come from my own troubleshooting. Thus far, support hasn't been much help and they've asked me to do things that would actually be counter-productive (for instance, they told me yesterday to re-add the catch-all to the main rule.....right).

    The behavior that I'm seeing now is that while I have two working rules, the secondary rule is not working as expected. As nearly as I can tell from my troubleshooting, the traffic being shunted to the secondary VIP isn't using the UDP profile applied to the secondary (which has datagram load balancing enabled), but the primary.

    Spark, I'm really glad you mentioned the return command, because I plan to test and see if adding a return after the traffic is shunted to the secondary VIP will somehow un-jam the gears, so to speak, and the traffic will start using the secondary VIP's UDP profile.

    Updated copies of the rules below.

    Any insights or theories besides the one that I postulated would be appreciated.

    Thanks again,

    Lucky

    [root@:Active] config  br syslog-pool-select-v5 syslog-tacacs-pool-select-v2 list
    rule syslog-pool-select-v5 {
       when CLIENT_ACCEPTED {
        set addr [IP::client_addr]
        switch $addr {
            xxx.xxx.xxx.xxx -
            xxx.xxx.xxx.xxx { virtual seim-syslog-tacacs }
        }
        if { [matchclass $addr starts_with $::syslog_chan1_string] }
        { pool syslog_pool_Channel_1 }
        elseif { [matchclass $addr starts_with $::syslog_chan2_string] }
        { pool syslog_pool_Channel_2 }
    }
    }
    rule syslog-tacacs-pool-select-v2 {
       when CLIENT_DATA {
        set paddr [findstr [UDP::payload] Address 8 ,]
        log local0.info "address $paddr"
        if { [matchclass $paddr starts_with $::xxxxxsubnetstring] } { set ::xxxxx 1
        log local0.info "I matched the xxxxx pool, YAY!.....addr $paddr" }
        else { set ::xxxxx 0
            log local0.info "selected syslog channel 1" }
    }
    when LB_SELECTED {
        set paddr [findstr [UDP::payload] Address 8 ,]
        switch $::xxxxx {
            1 { LB::reselect pool syslog_pool_xxxxx
                log local0.info "I selected the xxxxx pool, YAY!.....addr $paddr"
            }
        }
    }
    }
     
  • Can you add the return command and some debug logging and then reproduce the issue?

    rule syslog-pool-select-v5 {
    when CLIENT_ACCEPTED {
        switch [IP::client_addr] {
            xxx.xxx.xxx.xxx -
            xxx.xxx.xxx.xxx { virtual seim-syslog-tacacs; return }
        }
        if { [matchclass [IP::client_addr] starts_with syslog_chan1_string] }
        { pool syslog_pool_Channel_1 }
        elseif { [matchclass [IP::client_addr] starts_with syslog_chan2_string] }
        { pool syslog_pool_Channel_2 }
    }
    when LB_SELECTED {
        log local0. "[IP::client_addr]:[UDP_::client_port]: selected: [LB::server]"
    }
    when SERVER_CONNECTED {
        log local0. "[IP::client_addr]:[UDP_::client_port]: Connected: [IP::server_addr]:[UDP::server_port]"
    }
    }
    rule syslog-tacacs-pool-select-v2 {
    when CLIENT_DATA {
        set paddr [findstr [UDP::payload] Address 8 ,]
        log local0.info "address $paddr"
        if { [matchclass $paddr starts_with $::xxxxxsubnetstring] } { set ::xxxxx 1
        log local0.info "I matched the xxxxx pool, YAY!.....addr $paddr" }
        else { set ::xxxxx 0
            log local0.info "selected syslog channel 1" }
    }
    when LB_SELECTED {
        set paddr [findstr [UDP::payload] Address 8 ,]
        switch $::xxxxx {
            1 { LB::reselect pool syslog_pool_xxxxx
                log local0.info "I selected the xxxxx pool, YAY!.....addr $paddr"
            }
        }
    }
    when LB_SELECTED priority 501 {
        log local0. "[IP::client_addr]:[UDP_::client_port]: selected: [LB::server]"
    }
    when SERVER_CONNECTED {
        log local0. "[IP::client_addr]:[UDP_::client_port]: Connected: [IP::server_addr]:[UDP::server_port]"
    }
    }
    

    Aaron