Forum Discussion

keven_Wang_1124's avatar
keven_Wang_1124
Icon for Nimbostratus rankNimbostratus
Feb 23, 2006

Use BigIP to realize one to many TCP mapping

Hi all,

Our solution has to realize this scenario:

Many clients send http request to one gateway, this gateway open one TCP connection to BigIP and send these request to BIgIP, at this time these request's source IP are the IP of the gateway and BigIP use a http header named "x-nokia-ipaddress" to distinguish different clients and send them to different servers to handle these requests.

From the gateway to BigIP, we only use one TCP connection to send different clients' requests, but from BigIP to servers, we have to use several TCP connections (as they are from different clients and we need several servers to do load balancing). The problem is that when first client request comes, our iRules works well, but when second client request comes, our iRules doesn't work, it even doesn't be triggered.

Could BigIP realize one TCP to many TCP mapping from clientside to serverside? Could any one help us? Thanks very much!

Here is our iRules:


when HTTP_REQUEST
{
    set uri [HTTP::uri]
    set uritype [findstr $uri "cs?version" 0 "&"]
    if { $uritype ne "" }
    {
       set realclient [HTTP::header "x-nokia-ipaddress"]
       set key [list $realclient any]
       set peerip [session lookup uie $key]
       if {  $peerip equals "" }
       {
          snat $realclient
          LB::detach   
          pool CS_NIN_HTTP_Pool
       }
       else {
          snat $realclient
          node $peerip "9000"
       }
    }
    else
    {
       pool NIN_Web_Proxy_Pool 
    }
}
when HTTP_RESPONSE {
    set serverport [TCP::remote_port]
    if { $serverport equals "9000" }
    {
        set key [IP::local_addr]
        set key2 [list $key any]
        set oldvalue  [session lookup uie $key2]
        if { $oldvalue equals ""}
        {
           set value [IP::remote_addr]
           session add uie $key2  $value 120
        }
        log "http release"
        HTTP::release
     }       
}

  • drteeth_127330's avatar
    drteeth_127330
    Historic F5 Account
    You're saying that the HTTP_REQUEST event is not raised after the first request? Are you sure? Did you add a log statement at the top of the handler?

     

     

    Try removing the HTTP::release. It should not be necessary and may be causing problems.
  • Thanks!

    I have followed your suggestion and it seems that at the second time, the HTTP_REQUEST event also not be triggered.

    Here is our iRules:

    
    when HTTP_REQUEST
    {
        set uri [HTTP::uri]
        log "uri $uri"
        set uritype [findstr $uri "cs?version" 0 "&"]
        if { $uritype ne "" }
        {
           log "9000"
           set realclient [HTTP::header "x-nokia-ipaddress"]
           log "x-nokia-ipaddress: $realclient"
           set key [list $realclient any]
           set peerip [session lookup uie $key]
           if {  $peerip equals "" }
           {
              log " key not exist"
              LB::detach 
              snat $realclient  
              pool CS_NIN_HTTP_Pool
           }
           else {
              log " key exist" 
              log "x-nokia-ipaddress $realclient"
              snat $realclient
              node $peerip "9000"
           }
        }
        else
        {
           log "8080"
           pool NIN_Web_Proxy_Pool 
        }
    }
    when HTTP_RESPONSE {
        set serverport [TCP::remote_port]
        log "serverport : $serverport"
        if { $serverport equals "9000" }
        {
            log "server: [IP::remote_addr]"
            set key [IP::local_addr]
            set key2 [list $key any]
            set oldvalue  [session lookup uie $key2]
            log "respond :[HTTP::payload]"
            log "oldvalue: $oldvalue"
            if { $oldvalue equals ""}
            {
               set value [IP::remote_addr]
               log "in session add before $key2 ->$value"
               session add uie $key2  $value 120
               log "in session after add"
            }
            log "http release"
            HTTP::release
            TCP::close
            HTTP::collect
            LB::detach
            TCP::collect 
         }     
    }

    And I use a simple java client, here it is:

    
    import java.io.*;
    import java.net.*;
    import java.util.*;
    public class client_start3{
           public static void main(String []args){
         try{
    byte[] b = new byte[4]; 
     b[0] = new Integer(10).byteValue(); 
     b[1] = new Integer(128).byteValue(); 
     b[2] = new Integer(16).byteValue(); 
     b[3] = new Integer(51).byteValue(); 
            InetAddress addr1 =   InetAddress.getByAddress(b);
    Socket socket = new Socket(addr1,80);
    BufferedReader in = new BufferedReader(
      new InputStreamReader(socket.getInputStream()));
    PrintWriter out = new PrintWriter(new   BufferedWriter(
    new OutputStreamWriter(socket.getOutputStream())),
    true);
    out.println("GET /cs?version=1.0&cmd=start HTTP/1.1\r\nUser-Agent: UNTRUSTED/1.0\r\nContent-Length: 0\r\nx-nokia-ipaddress:10.128.16.44\r\nHost:10.128.16.51:80\r\n");
    while(true){
         String str = in.readLine();
         System.out.println(str);
         if(str==null)
    break;
    }
                    out.flush();
    try{
        Thread.currentThread().sleep(5000);
    }catch(Exception e){}
    out.println("GET /cs?version=1.0&cmd=start HTTP/1.1\r\nUser-Agent: UNTRUSTED/1.0\r\nContent-Length: 0\r\nx-nokia-ipaddress:10.128.16.105\r\nHost:10.128.16.51:80\r\n");
    while(true){
         String str = in.readLine();
                         if(str==null)
    break;
         System.out.println(str);
    }
    while(true){}
       }
       catch(Exception e){
    System.out.println(e.toString());
       }
    }
    }

    This is the log when I use java client to test this iRules.

    Feb 24 17:16:23 tmm tmm[756]: 01220002:6: Rule sfrhttp : uri /cs?version=1.0&cmd=start
    Feb 24 17:16:23 tmm tmm[756]: 01220002:6: Rule sfrhttp : 9000
    Feb 24 17:16:23 tmm tmm[756]: 01220002:6: Rule sfrhttp : x-nokia-ipaddress: 10.128.16.44
    Feb 24 17:16:23 tmm tmm[756]: 01220002:6: Rule sfrhttp :  key not exist
    Feb 24 17:16:23 tmm tmm[756]: 01220002:6: Rule sfrhttp : serverport : 9000
    Feb 24 17:16:24 tmm tmm[756]: 01220002: repeated 4 times

    Could you give me some suggestion? Thanks very much!
  • drteeth_127330's avatar
    drteeth_127330
    Historic F5 Account
    This sounds like a bug. The HTTP_REQUEST event should be raised for each request. I recommend that you contact F5 support.

     

     

    It would help if you could try removing statements from the rule until you can isolate the problem. For example, what happens when you remove the LB::detach? I realize that it is required to choose a different source address for two requests to the same pool, but perhaps it is causing the problem. Another possibility is that there is something wrong with the response from the server. Does anything appear in the BIG-IP logs? Is the server returning a 200 OK status code? Can you get a packet capture of the problem ocurring?
  • I know why! When LB sends response first time, it closed the TCP session, so when client sends HTTP request next time, it could not trigger this iRules. Now I have configured oneconnect profile for the virtual server which use this iRules, and LB doesn't close the TCP session now, so everything works well now.

     

    Thanks very much.