Forum Discussion

Matt_Breedlove_'s avatar
Matt_Breedlove_
Icon for Nimbostratus rankNimbostratus
Apr 24, 2007

TCP Payload String Swap for Oracle HA

Hi,

 

 

I would like to use an iRule on a VIP that heads 4 Oracle DB RAC servers. Each server helps serve a single DB on SAN attached storage. However, Oracle requires that each rac host have a unique SID.

 

So host db01 uses SID "acmesid1"

 

So host db02 uses SID "acmesid2"

 

So host db03 uses SID "acmesid3"

 

So host db04 uses SID "acmesid4"

 

 

The application servers which use the database hosted by these 4 RAC servers can only have a single SID configured.

 

 

I would like the Application server to be configured with "acmesid_vip" and when when the application server hits the BigIP on port 1521 with this SID in tow the BigIP will open the TCP Payload and swap this incoming SID "acmesid_vip" with "acmesid1" or "acmesid2" or "acmesid3" or "acmesid4" based on which DB server the BigIP is planning on forwarding the request to, respectivley.

 

 

So in short is there a way to do a regular expression on the TCP payload of all incoming packets s/acmesid_vip/acmesid1/ in the case of going to the first DB server?

 

 

I have seen the TCP::payload function and this is what I have so far which I am sure is horribly busted as it uses a mix of pseudo code to get my goal across as I am no irules guru

 

 

What do you think?

 

 


set payload [TCP::payload]
   if { destDBHost=db01 } {
   set END_SID "acmesid1"
   regsub -all "(acmesid_vip)" $payload "\\1\\2$END_SID" payload
   TCP::payload replace 0 [TCP::payload length] $payload
   }
   if { destDBHost=db02 } {
   set END_SID "acmesid2"
   regsub -all "(acmesid_vip)" $payload "\\1\\2$END_SID" payload
   TCP::payload replace 0 [TCP::payload length] $payload
   }
   if { destDBHost=db03 } {
   set END_SID "acmesid3"
   regsub -all "(acmesid_vip)" $payload "\\1\\2$END_SID" payload
   TCP::payload replace 0 [TCP::payload length] $payload
   }
   if { destDBHost=db04 } {
   set END_SID "acmesid3"
   regsub -all "(acmesid_vip)" $payload "\\1\\2$END_SID" payload
   TCP::payload replace 0 [TCP::payload length] $payload
   }
  • Deb_Allen_18's avatar
    Deb_Allen_18
    Historic F5 Account
    Hi Matt --

    Here's the basic iRule version of your pseudocode above:
    rule RAC-SID-replacement_switch {
    when CLIENT_ACCEPTED {
      TCP::collect
    }
    when CLIENT_DATA {
      set payload [TCP::payload]
    }
    when LB_SELECTED {
      switch [LB::server addr] {
        10.10.10.1 { ;  IP addr of vfcudb01b
          regsub -all "acmesid_vip" $payload "acmesid1" payload
          TCP::payload replace 0 [TCP::payload length] $payload
        }
        10.10.10.2 { ;  IP addr of vfcudb02b
          regsub -all "acmesid_vip" $payload "acmesid2" payload
          TCP::payload replace 0 [TCP::payload length] $payload
        }
        10.10.10.3 { ;  IP addr of vfcudb03b
          regsub -all "acmesid_vip" $payload "acmesid3" payload
          TCP::payload replace 0 [TCP::payload length] $payload
        }
        10.10.10.4 { ;  IP addr of vfcudb04b
          regsub -all "acmesid_vip" $payload "acmesid4" payload
          TCP::payload replace 0 [TCP::payload length] $payload
        }
      }
      TCP::release
      TCP::collect
    }
    }
    For a more concise and scalable solution, you could instead use a class to maintain the relationship between IP, hostname, and sid value, and extract with "findclass" (Although in this example the hostname field is not necessary, it might be useful as a label/comment for admin purposes):
    class mySIDs {
       type string
      10.10.10.1 acmesid1 vfcudb01b 
      10.10.10.2 acmesid2 vfcudb02b
      10.10.10.3 acmesid3 vfcudb03b
      10.10.10.4 acmesid4 vfcudb04b
    }
    rule RAC-SID-replacement_findclass {
    when CLIENT_ACCEPTED {
      TCP::collect
    }
    when CLIENT_DATA {
      set payload [TCP::payload]
    }
    when LB_SELECTED {
      set mySID [getfield [findclass [LB::server addr] $::mySIDs] " " 2]
      if {$mySID != ""}{
        regsub -all "acmesid_vip" $payload "$mySID" payload
        TCP::payload replace 0 [TCP::payload length] $payload
      }
      TCP::release
      TCP::collect
    }
    }

    Requests traversing either iRule will be forwarded to the VS's configured default pool regardless of whether any payload manipulation took place. The release/collect at the end ensures that subsequent requests on the same connection will be processed in the same manner.

    HTH

    (I'd be interested to hear back if this solved your problem so I can add it to the CodeShare.)

    /deb

  • Thanks much, hopefully we can try this out in our staging environment and see if it works properly. If so I think there will be a lot of people and organizations that will be able to take advantage of this method that does not require any application server to be Oracle RAC aware.

     

     

    Once we get some more info, will post back