FIX Select Pool Based On Sender Comp ID

Problem this snippet solves:

Financial Information eXchange (FIX) Protocol iRule to select pool based on Sender Comp ID. This rule leverages matchclass so should only be used with v9. If using v10 or v11, please use class match.

Code :

# iRule Source
# Updated for v11.5 with the use of the FIX_MESSAGE event and the FIX::field command
# Note that this version requires the use of the FIX profile included in BIG-IP v11.5 to function
# It also requires a datagroup named "sendercompidlist" with name value pairs of sendercompid:destination_pool

when FIX_MESSAGE {
  log local0. "fix-select-sendercompid: [IP::client_addr] is using SenderCompID [FIX::field 49]"
  set poolname [class lookup [FIX::field 49] equals sendercompidlist]
  if {$poolname eq ""} {
    log local0. "[IP::client_addr] with SenderCompID- [FIX::field 49] was not found fix-selectcompid"
    discard
  } else {
    log local0. "[IP::client_addr] is using $poolname"
    pool $poolname
  }
}


# Requirements:
#

class SenderCompIDListA extern {
   type string
   filename "/var/class/SenderCompIDListA"
}
class SenderCompIDListB extern {
   type string
   filename "/var/class/SenderCompIDListB"
}

# For 4.5 the last variable should exclude the comma  
# 
Contents of /var/class/SenderCompIDListA :
"SENDERCOMPID1",

Contents of /var/class/SenderCompIDListB :
"SENDERCOMPID2",

#
# Financial Information eXchange (FIX) Protocol iRule 
# to select pool based on SenderCompID. (9.x)
#
# 03/16/06 - Updated regex to be more precise
# 
# By Brad A. 
when RULE_INIT {    
log local0. "fix-select-sendercompid rule loading..."  
}

when CLIENT_ACCEPTED {
log local0. "fix-select-sendercompid: accepted client"
         TCP::collect
}
when CLIENT_DATA {
set clientip [IP::client_addr]
log local0. "fix-select-sendercompid: accepted client- $clientip"
 if {[regexp "\x0149=(.*)\x0156" [TCP::payload] -> SenderCompID]} {
log local0. "fix-select-sendercompid: $clientip is using SenderCompID $SenderCompID"
        if { [matchclass $SenderCompID contains $::SenderCompIDListA] } {
            log local0. "$clientip is using fixpool1"
            use pool fixpool1
TCP::release
        }
        elseif { [matchclass $SenderCompID contains $::SenderCompIDListB] } {
            log local0. "$clientip is using fixpool2"
use pool fixpool2
TCP::release           
        }
        else {
            log local0. "$clientip with SenderCompID- $SenderCompID was not found for fix-selectcompid"
            TCP::close
           }
    }
else {
log local0. "Could not find SenderCompID for client $clientip"
                  TCP::close
}
}
#

#
# Financial Information eXchange (FIX) Protocol iRule 
# to select pool based on SenderCompID.
#
# For 4.5
# 
# By Brad A. 

log "Loading Rule"
log "Client: " + client_addr + " SenderCompID: " + getfield(tcp_content, '=', 5)
if (getfield(tcp_content, '=', 5) contains one of SenderCompIDListA) {
   log "Client: " + client_addr + " is using pool pool1"
   use pool pool1
}
else if (getfield(tcp_content, '=', 5) contains one of SenderCompIDListB) {
   log "Client: " + client_addr + " is using pool pool2"
   use pool pool2
}
else {
   log "Client: " + client_addr + " could not match SenderCompID"
   discard
}
#

# Updated for version 10.x and 11.x
# By John Alam, 09-2011.

# This version uses the node command and does a lookup for the IP and port of the node
# using the CompID as the key.

# You can use internal or external data groups.
# This irule expects the external data group to look like this:
# 
#     /config/SenderCompIDList:
#     "/100/" := "10.0.0.1-5050",
#     "/101/" := "10.0.0.1-5051",
#     "/102/" := "10.0.0.2-5050",

#    class SenderCompIDList {
#       type string
#       filename SenderCompIDList.dat
#   }



when RULE_INIT {    
log local0. "fix-select-sendercompid rule loading..."  
}

when CLIENT_ACCEPTED {
log local0. "fix-select-sendercompid: accepted client"
    TCP::collect
}
when CLIENT_DATA {
set clientip [IP::client_addr]
log local0. "fix-select-sendercompid: accepted client- $clientip"
 if {[regexp "\x0149=(.*)\x0156" [TCP::payload] -> SenderCompID]} {
log local0. "fix-select-sendercompid: $clientip is using SenderCompID $SenderCompID"
set FIX_engine [class lookup $SenderCompID equals SenderCompIDList]
if { not ($FIX_engine equals "")} {
set node_ip [getfield $FIX_engine "-" 1]
set node_port [getfield $FIX_engine "-" 2]
            log local0. "$SenderCompID is using $node_ip:$node_port"
node $node_ip $node_port
TCP::release
        } else {
log local0. "CompID $SenderCompI not found in datagroup."
           TCP::close
}
   }
else {
log local0. "Could not find SenderCompID in TCP payload for client $clientip"
        TCP::close
}
}
Published Mar 17, 2015
Version 1.0

Was this article helpful?

No CommentsBe the first to comment