Forum Discussion

Segman_342030's avatar
Segman_342030
Icon for Nimbostratus rankNimbostratus
Nov 26, 2017

LB for SMPP / SMSCs in NFV environment

Hi all, We are trying to use the LMT F5 (installed on Openstack) to be SMSC Getaway (Short Message Service Center – Getaway) for external messages Our installation is based on minimum 2 SMSCs, and Maximum 8 SMSCs

 

So, if an external application will connect to the SMSCs, the F5 will get the connection request (bind) and will try to connect to all active SMSCs with the same bind connection For messages running on top the active connection (submit_sm), the F5 will do a round robin between all the active SMSCs.

 

Connection from Client & message from SMSC:

 

  • 1:: Client1 ---(bind)---> F5
  • 1-1:: F5 ----(bind)----> SMSC1
  • 1-2:: F5 ----(bind)----> SMSC2.... (max of 8 SMSCs)
  • 1-1':: SMSC1 -----(bind_resp1)----->F5
  • 1-2':: SMSC2 -----(bind_resp2)----->F5.... (max of 8 SMSCs)
  • 2:: If (bind_resp1 = OK) or (bind_resp2 = OK) or (max 8 SMSCs); respond back to Client1 with OK
  • 2:: Else; respond back with NOK
  • 3:: SMSC1 ----(deliver_sm1)---->F5 [store sequence, use internal sequence]
  • 3-1:: F5 ----(deliver_sm1)---->Client1
  • 4:: SMSC2 ----(deliver_sm2)---->F5 [store sequence, use internal sequence]
  • 4-1:: F5 ----(deliver_sm2)---->Client1
  • 4-1':: Client1 ----(deliver_sm_resp2)---->F5
  • 3-1':: Client1 ----(deliver_sm_resp1)---->F5
  • 4-1'':: F5 ----(deliver_sm_resp2)---->SMSC2 [use original sequence]
  • 3-1'':: F5 ----(deliver_sm_resp1)---->SMSC1 [use original sequence]

Connection from Client & message from Client:

 

  • 1:: Client1 ---(bind)---> F5
  • 1-1:: F5 ----(bind)----> SMSC1
  • 1-2:: F5 ----(bind)----> SMSC2.... (max of 8 SMSCs)
  • 1-1':: SMSC1 -----(bind_resp1)----->F5
  • 1-2':: SMSC2 -----(bind_resp2)----->F5.... (max of 8 SMSCs)
  • 2:: If (bind_resp1 = OK) or (bind_resp2 = OK); respond back to Client1 with OK
  • 2:: Else; respond back with NOK
  • 3:: Client1 ----(deliver_sm1)---->F5 [store sequence, use internal sequence]
  • 4-1:: F5 ----(deliver_sm1)---->SMSC using Round Robin [store sequence, use internal sequence]
  • 4-1':: SMSC ----(deliver_sm_resp1)---->F5 [use original sequence]
  • 3-1':: F5----(deliver_sm_resp1)---->Client1 [use original sequence]
  • help with what?

     

    im afraid this will be a little beyond what you can expect from a community forum to help you with. if you have a specific issue sure, but this feels like a whole implementation that doesn't work out (and you fail to explain what doesn't work).

     

    you might consider contacting your local f5 sales team and asking for a f5 partner or professional services if this is important.

     

  • when CLIENT_ACCEPTED { set seq_index 1 set bind_context 0

    set unbind_context 0
    TCP::collect
    

    }

    when CLIENT_DATA { while { [TCP::payload length] > 16 } { binary scan [TCP::payload] IH8IIa* RQTLen RQTOper RQTStatus RQTSeq p if { [TCP::payload length] < $RQTLen } { TCP::collect $RQTLen return }

        switch -glob $RQTOper {
            00000001 -
            00000002 - 
            00000009 {
                bind
    
                log local0.info "SMPP:BindRequest Data: LEN:$RQTLen Command:$RQTOper Satus:$RQTStatus Seqence:$RQTSeq"
                set bind_message [TCP::payload $RQTLen]
                set bind_context 1
                foreach smsc_node [active_members -list pool_smsc] { 
    
                    set node [lindex [split $smsc_node " "] 0]:[lindex [split $smsc_node " "] 1]
                    set smsc($smsc_node) "0 0 0"
                    foreach {smsc_node_1} [array get smsc]
                    {
                        log local0.info "ARRAY_ELEMENT_1 ==> $smsc_node_1"
                    }
                }
            }           
            00000006 {
                unbind
                log local0.info "SMPP:UnbindRequest Data:LEN:$RQTLen Command:$RQTOper Satus:$RQTStatus Seqence:$RQTSeq"
                set unbind_message [TCP::payload $RQTLen]               
                set unbind_context 1
            }
    
            00000015 {
                enquire_link
                log local0.info "SMPP:enquireLinkRequest Data:LEN:$RQTLen Command:$RQTOper Satus:$RQTStatus Seqence:$RQTSeq"
                set enquire_message [TCP::payload $RQTLen]
                foreach {smsc_node b_status u_status el_status} [array get smsc] {  
                    array set smsc {$smsc_node "$b_status $u_status 0"}
                }
            }
    
            00000004 {
                submit_sm
                log local0.info "SMPP:SubmitSMRequest Data:LEN:$RQTLen Command:$RQTOper Satus:$RQTStatus Seqence:$RQTSeq"
                Load balance SMS AO
                LB::detach
            }
    
            8* {
                Response from client (deliver_sm_resp, ...)
                log local0.info "SMPP:CommandResponse Data:LEN:$RQTLen Command:$RQTOper Satus:$RQTStatus Seqence:$RQTSeq"
                Rewrite RQTSeq and set the correct SMS-C to respond
                if { [info exists s_seq_map($RQTSeq)] } {
                    set old_RQTSeq [lindex $s_seq_map($RQTSeq) 0]
                    TCP::payload replace 12 4 [binary format I $seq_index]
                     use pool or node command
                    pool [LB::server pool] member [lindex $s_seq_map($RQTSeq) 1] [lindex $s_seq_map($RQTSeq) 2]
                    unset s_seq_map($RQTSeq)
                } else {
                    Cannot route response
                    log local0.info "SMPP:Unkown sequence [$RQTSeq] Data:LEN:$RQTLen Command:$RQTOper Satus:$RQTStatus Seqence:$RQTSeq"
                }
            }
        }
        TCP::release $RQTLen
        TCP::notify request
    }
    TCP::collect
    

    }

    when SERVER_CONNECTED {

    TCP::collect

    }

    when SERVER_DATA { while { [TCP::payload length] > 16 } { binary scan [TCP::payload] IH8II RQTLen RQTOper RQTStatus RQTSeq p if { [TCP::payload length] < $RQTLen } { TCP::collect $RQTLen return } switch -glob $RQTOper {

    0* { Deliver_sm, ... Rewrite seq TCP::payload replace 12 4 [binary format I $seq_index] set s_seq_map($seq_index) "$RQTSeq [IP::remote_addr] [TCP::remote_port]" incr seq_index }
            80000001 - 
            80000002 - 
            80000009 {
                Bind_resp
                if { $bind_context } {
                    switch -glob $RQTStatus {                       
                        00000000 - 
                        0 -
                        00000005 {
                            No Error or ESME Already in Bound State
                            log local0.info "Bind:ResponseOK Data: Status:$RQTStatus Node: [IP::remote_addr] [TCP::remote_port] "
    
                            Added by YOSSI
                            set smsc("[IP::remote_addr]:[TCP::remote_port]") "1 0 0"
    
                            foreach {smsc_node b_status} [array get smsc] {
                            log local0.info "smsc_node_res $smsc_node"
                                if { $b_status eq "0 0 0" } {
                                    log local0.info "Bind:OneMoreSMSCToBind Data:\[Node: $smsc_node \]"
                                    log local0. " node [lindex [split $smsc_node " "] 0] port [lindex [split $smsc_node " "] 1]"
                                    set a [lindex [split $smsc_node " "] 0]:[lindex [split $smsc_node " "] 1]
                                    log local0.info "a $a"
                                    pool pool_smsc member $a
                                    TCP::collect -all
                                    TCP::respond $bind_message
                                    set smsc("$a") "1 0 0"
                                    log local0.info "smsc("$a")"
                                    return
                                }
    
    
                            }
    
                            log local0.info "Bind:NoMoreSMSCToBind Data:\[SMSC: $smsc_node \]"
                        }
    
                        *
                        {
                            Else - Respond back to client
                            log local0.info "Bind:ResponseFailed Data: Status:$RQTStatus Node: [IP::remote_addr] [TCP::remote_port] ]"                         
                        }                       
                    }
                    set bind_context 0        
                } else {
                    log local0.info "Bind:UnknownContext Data:Status:$RQTStatus Node: [IP::remote_addr] [TCP::remote_port] "
                    TCP::payload replace 0 [TCP::payload length] ""
                    set RQTLen 0
                }
            }
    
            80000006 {
                Unbind_resp
                if { $unbind_context }  {
                    log local0.info "Unbind:Response Data: Status:$RQTStatus Node: [IP::remote_addr] [TCP::remote_port] "
                    set memb "[IP::remote_addr] [TCP::remote_port]"
                    array set smsc {$memb "1 1 0"}
                    foreach {smsc_node b_status u_status el_status} [array get smsc] {
                        if {$u_status eq 0} {
                            log local0.info "Unbind:OneMoreSMSCToUnbind Data:\[Node: $smsc_node \]"
                            pool pool_smsc member $smsc_node
                            TCP::collect -all
                            TCP::respond $unbind_message
                            return                          
                        }
                    }
                    log local0.info "Unbind:NoMoreSMSCToUnbind Data"
                } else {
                    log local0.info "Unbind:UnknownContext Data:Status:$RQTStatus Node: [IP::remote_addr] [TCP::remote_port] "
                    TCP::payload replace 0 [TCP::payload length] ""
                    set RQTLen 0
                }
    
                set unbind_context 0
                unset smsc;
            }
    
            80000015 {
                Enquire_link_resp
                log local0.info "Enquire_link:Response Data: Status:$RQTStatus Node: [IP::remote_addr] [TCP::remote_port] "
                set memb "[IP::remote_addr] [TCP::remote_port]"
                array set smsc {$memb "1 1 0"}
                foreach {smsc_node b_status u_status el_status} [array get smsc] {
                    if {$el_status eq 0} {
                        log local0.info "Enquire_link:OneMoreSMSCToEnquireLink Data:\[Node: $smsc_node \]"
                        pool pool_smsc member $smsc_node
                        TCP::collect -all
                        TCP::respond $enquire_message
                        return                      
                    }
                }
                log local0.info "Enquire_link:NoMoreSMSCToEnquireLink Data"                
            }
        }
        TCP::release $RQTLen
        TCP::notify response
    }
    TCP::collect
    

    }