Navigation


Changeset 706:4ffbc9f1e922 in freeDiameter for libfdcore/p_dp.c


Ignore:
Timestamp:
Feb 9, 2011, 3:26:58 PM (13 years ago)
Author:
Sebastien Decugis <sdecugis@nict.go.jp>
Branch:
default
Phase:
public
Message:

Large UNTESTED commit with the following changes:

  • Improved DiameterIdentity? handling (esp. interationalization issues), and improve efficiency of some string operations in peers, sessions, and dictionary modules (closes #7)
  • Cleanup in the session module to free only unreferenced sessions (#16)
  • Removed fd_cpu_flush_cache(), replaced by more robust alternatives.
  • Improved peer state machine algorithm to counter SCTP multistream race condition.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libfdcore/p_dp.c

    r662 r706  
    3838/* This file contains code to handle Disconnect Peer messages (DPR and DPA) */
    3939
     40/* Delay to use before next reconnect attempt */
     41int fd_p_dp_newdelay(struct fd_peer * peer)
     42{
     43        int delay = peer->p_hdr.info.config.pic_tctimer ?: fd_g_config->cnf_timer_tc;
     44       
     45        switch (peer->p_hdr.info.runtime.pir_lastDC) {
     46                case ACV_DC_REBOOTING:
     47                default:
     48                        /* We use TcTimer to attempt reconnection */
     49                        break;
     50                case ACV_DC_BUSY:
     51                        /* No need to hammer the overloaded peer */
     52                        delay *= 10;
     53                        break;
     54                case ACV_DC_NOT_FRIEND:
     55                        /* He does not want to speak to us... let's retry a *lot* later maybe */
     56                        delay *= 200;
     57                        break;
     58        }
     59        return delay;
     60}
     61
    4062/* Handle a received message */
    4163int fd_p_dp_handle(struct msg ** msg, int req, struct fd_peer * peer)
     
    4466       
    4567        if (req) {
    46                 /* We received a DPR, save the Disconnect-Cause and terminate the connection */
     68                /* We received a DPR, save the Disconnect-Cause and go to CLOSING_GRACE or terminate the connection */
    4769                struct avp * dc;
    48                 int delay = peer->p_hdr.info.config.pic_tctimer ?: fd_g_config->cnf_timer_tc;
    4970               
    5071                CHECK_FCT( fd_msg_search_avp ( *msg, fd_dict_avp_DC, &dc ));
    5172                if (dc) {
    52                         /* Check the value is consistent with the saved one */
    5373                        struct avp_hdr * hdr;
    5474                        CHECK_FCT(  fd_msg_avp_hdr( dc, &hdr )  );
     
    6080                        }
    6181
     82                        /* save the cause */
    6283                        peer->p_hdr.info.runtime.pir_lastDC = hdr->avp_value->u32;
    63                        
    64                         switch (hdr->avp_value->u32) {
    65                                 case ACV_DC_REBOOTING:
    66                                 default:
    67                                         /* We use TcTimer to attempt reconnection */
    68                                         break;
    69                                 case ACV_DC_BUSY:
    70                                         /* No need to hammer the overloaded peer */
    71                                         delay *= 10;
    72                                         break;
    73                                 case ACV_DC_NOT_FRIEND:
    74                                         /* He does not want to speak to us... let's retry a lot later maybe */
    75                                         delay *= 200;
    76                                         break;
    77                         }
    7884                }
    7985                if (TRACE_BOOL(INFO)) {
    8086                        if (dc) {
    81                                 struct dict_object * dictobj = NULL;
     87                                struct dict_object * dictobj;
    8288                                struct dict_enumval_request er;
    8389                                memset(&er, 0, sizeof(er));
     90                               
     91                                /* prepare the request */
    8492                                CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, fd_dict_avp_DC, &er.type_obj, ENOENT )  );
    8593                                er.search.enum_value.u32 = peer->p_hdr.info.runtime.pir_lastDC;
     94                               
     95                                /* Search the enum value */
    8696                                CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &er, &dictobj, 0 )  );
    8797                                if (dictobj) {
     
    100110                CHECK_FCT( fd_msg_rescode_set( *msg, "DIAMETER_SUCCESS", NULL, NULL, 1 ) );
    101111               
    102                 /* Move to CLOSING state to failover outgoing messages (and avoid failing the DPA...) */
     112                /* Move to CLOSING state to failover outgoing messages (and avoid failing over the DPA...) */
    103113                CHECK_FCT( fd_psm_change_state(peer, STATE_CLOSING) );
    104114               
     
    106116                CHECK_FCT( fd_out_send( msg, NULL, peer, FD_CNX_ORDERED) );
    107117               
    108                 /* Move to CLOSED state */
    109                 fd_psm_cleanup(peer, 0);
    110                
    111                 /* Reset the timer for next connection attempt -- we'll retry sooner or later depending on the disconnection cause */
    112                 fd_psm_next_timeout(peer, 1, delay);
    113                
     118                if (fd_cnx_isMultichan(peer->p_cnxctx)) {
     119                        /* There is a possibililty that messages are still in the pipe coming here, so let's grace for 1 second */
     120                        CHECK_FCT( fd_psm_change_state(peer, STATE_CLOSING_GRACE) );
     121                        fd_psm_next_timeout(peer, 0, 1);
     122                       
     123                } else {
     124                        /* Move to CLOSED state */
     125                        fd_psm_cleanup(peer, 0);
     126
     127                        /* Reset the timer for next connection attempt -- we'll retry sooner or later depending on the disconnection cause */
     128                        fd_psm_next_timeout(peer, 1, fd_p_dp_newdelay(peer));
     129                }
    114130        } else {
    115131                /* We received a DPA */
    116                 fd_cpu_flush_cache();
    117                 if (peer->p_hdr.info.runtime.pir_state != STATE_CLOSING) {
    118                         TRACE_DEBUG(INFO, "Ignoring DPA received in state %s", STATE_STR(peer->p_hdr.info.runtime.pir_state));
     132                int curstate = fd_peer_getstate(peer);
     133                if (curstate != STATE_CLOSING) {
     134                        TRACE_DEBUG(INFO, "Ignoring DPA received in state %s", STATE_STR(curstate));
    119135                }
    120136                       
    121137                /* In theory, we should control the Result-Code AVP. But since we will not go back to OPEN state here anyway, let's skip it */
     138               
     139                /* TODO("Control Result-Code in the DPA") */
    122140                CHECK_FCT_DO( fd_msg_free( *msg ), /* continue */ );
    123141                *msg = NULL;
    124142               
    125                 /* The calling function handles cleaning the PSM and terminating the peer since we return in CLOSING state */
     143                if (fd_cnx_isMultichan(peer->p_cnxctx)) {
     144                        CHECK_FCT( fd_psm_change_state(peer, STATE_CLOSING_GRACE) );
     145                        fd_psm_next_timeout(peer, 0, 1);
     146                        peer->p_flags.pf_localterm = 1;
     147                }
     148                /* otherwise, return in CLOSING state, the psm will handle it */
    126149        }
    127150       
     
    153176        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, fd_dict_avp_DC, &er.type_obj, ENOENT )  );
    154177        er.search.enum_name = reason ?: "REBOOTING";
    155         CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &er, &dictobj, ENOENT )  );
     178        CHECK_FCT_DO( fd_dict_search( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &er, &dictobj, ENOENT ), { ASSERT(0); /* internal error: unknown reason */ }  );
    156179        CHECK_FCT( fd_dict_getval( dictobj, &er.search ) );
    157180       
Note: See TracChangeset for help on using the changeset viewer.