Navigation


Changeset 88:9e2db1647d6f in freeDiameter


Ignore:
Timestamp:
Dec 7, 2009, 3:51:09 PM (14 years ago)
Author:
Sebastien Decugis <sdecugis@nict.go.jp>
Branch:
default
Phase:
public
Message:

Completed routing module

Files:
2 edited

Legend:

Unmodified
Added
Removed
  • freeDiameter/routing.c

    r87 r88  
    266266{
    267267        struct fd_peer * peer;
     268        int is_loc = 0;
    268269
    269270        /* Get the source of the message */
     
    272273                CHECK_FCT( fd_msg_source_get( msg, &id ) );
    273274               
    274                 /* Search the peer with this id */
    275                 CHECK_FCT( fd_peer_getbyid( id, (void *)&peer ) );
    276                
    277                 if (!peer) {
    278                         TRACE_DEBUG(INFO, "Unable to send error '%s' to deleted peer '%s' in reply to:", error_code, id);
    279                         fd_msg_dump_walk(INFO, msg);
    280                         fd_msg_free(msg);
    281                         return 0;
     275                if (id == NULL) {
     276                        is_loc = 1; /* The message was issued locally */
     277                } else {
     278               
     279                        /* Search the peer with this id */
     280                        CHECK_FCT( fd_peer_getbyid( id, (void *)&peer ) );
     281
     282                        if (!peer) {
     283                                TRACE_DEBUG(INFO, "Unable to send error '%s' to deleted peer '%s' in reply to:", error_code, id);
     284                                fd_msg_dump_walk(INFO, msg);
     285                                fd_msg_free(msg);
     286                                return 0;
     287                        }
    282288                }
    283289        }
     
    290296
    291297        /* Send the answer */
    292         CHECK_FCT( fd_out_send(&msg, NULL, peer) );
     298        if (is_loc) {
     299                CHECK_FCT( fd_fifo_post(fd_g_incoming, &msg) );
     300        } else {
     301                CHECK_FCT( fd_out_send(&msg, NULL, peer) );
     302        }
    293303       
    294304        /* Done */
     
    548558{
    549559        TRACE_ENTRY("%p", arg);
     560        struct rt_data * rtd = NULL;
    550561       
    551562        /* Set the thread name */
     
    563574                struct msg_hdr * hdr;
    564575                int is_req = 0;
     576                struct fd_list * li, *candidates;
     577                struct avp * avp;
     578                struct rtd_candidate * c;
     579               
     580                /* If we loop'd with some undeleted routing data, destroy it */
     581                if (rtd != NULL)
     582                        fd_rtd_free(&rtd);
    565583               
    566584                /* Test if we were told to stop */
     
    583601                        struct msg * qry;
    584602                        char * qry_src = NULL;
     603                        struct msg_hdr * qry_hdr;
    585604                        struct fd_peer * peer = NULL;
    586605                       
     
    600619                        }
    601620                       
     621                        /* We must restore the hop-by-hop id */
     622                        CHECK_FCT_DO( fd_msg_hdr(qry, &qry_hdr), goto fatal_error );
     623                        hdr->msg_hbhid = qry_hdr->msg_hbhid;
     624                       
    602625                        /* Push the message into this peer */
    603626                        CHECK_FCT_DO( fd_out_send(&msg, NULL, peer), goto fatal_error );
     
    607630                }
    608631               
    609                 /* The message is a request */
    610                 TODO("use struct rt_data and fd_msg_rt_get");
     632                /* From that point, the message is a request */
     633               
     634                /* Get the routing data out of the message if any (in case of re-transmit) */
     635                CHECK_FCT_DO( fd_msg_rt_get ( msg, &rtd ), goto fatal_error );
     636               
     637                /* If there is no routing data already, let's create it */
     638                if (rtd == NULL) {
     639                        CHECK_FCT_DO( fd_rtd_init(&rtd), goto fatal_error );
     640                       
     641                        /* Add all peers in OPEN state */
     642                        CHECK_FCT_DO( pthread_rwlock_wrlock(&fd_g_activ_peers_rw), goto fatal_error );
     643                        for (li = fd_g_activ_peers.next; li != &fd_g_activ_peers; li = li->next) {
     644                                struct fd_peer * p = (struct fd_peer *)li->o;
     645                                CHECK_FCT_DO( fd_rtd_candidate_add(rtd, p->p_hdr.info.pi_diamid), goto fatal_error);
     646                        }
     647                        CHECK_FCT_DO( pthread_rwlock_unlock(&fd_g_activ_peers_rw), goto fatal_error );
     648                       
     649                        /* Now let's remove all peers from the Route-Records */
     650                        CHECK_FCT_DO(  fd_msg_browse(msg, MSG_BRW_FIRST_CHILD, &avp, NULL), goto fatal_error  );
     651                        while (avp) {
     652                                struct avp_hdr * ahdr;
     653                                CHECK_FCT_DO(  fd_msg_avp_hdr( avp, &ahdr ), goto fatal_error  );
     654                               
     655                                if ((ahdr->avp_code == AC_ROUTE_RECORD) && (! (ahdr->avp_flags & AVP_FLAG_VENDOR)) ) {
     656                                        /* Parse this AVP */
     657                                        CHECK_FCT_DO( fd_msg_parse_dict ( avp, fd_g_config->cnf_dict ), goto fatal_error );
     658                                        ASSERT( ahdr->avp_value );
     659                                        /* Remove this value from the list */
     660                                        fd_rtd_candidate_del(rtd, (char *)ahdr->avp_value->os.data, ahdr->avp_value->os.len);
     661                                }
     662                               
     663                                /* Go to next AVP */
     664                                CHECK_FCT_DO(  fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL), goto fatal_error  );
     665                        }
     666                }
     667               
     668                /* Note: we reset the scores and pass the message to the callbacks, maybe we could re-use the saved scores when we have received an error ? */
     669               
     670                /* Ok, we have our list in rtd now, let's (re)initialize the scores */
     671                fd_rtd_candidate_extract(rtd, &candidates);
     672               
     673                /* Pass the list to registered callbacks (even if it is empty) */
     674                {
     675                        CHECK_FCT_DO( pthread_rwlock_rdlock( &rt_out_lock ), goto fatal_error );
     676                        pthread_cleanup_push( fd_cleanup_rwlock, &rt_out_lock );
     677                       
     678                        /* We call the cb by reverse priority order */
     679                        for (   li = rt_out_list.prev ; li != &rt_out_list ; li = li->prev ) {
     680                                struct rt_hdl * rh = (struct rt_hdl *)li;
     681                               
     682                                TRACE_DEBUG(ANNOYING, "Calling next OUT callback on %p : %p (prio %d)", msg, rh->rt_out_cb, rh->prio);
     683                                CHECK_FCT_DO( (*rh->rt_out_cb)(rh->cbdata, msg, candidates),
     684                                        {
     685                                                TRACE_DEBUG(INFO, "An OUT routing callback returned an error ! Message discarded.");
     686                                                fd_msg_dump_walk(INFO, msg);
     687                                                fd_msg_free(msg);
     688                                                msg = NULL;
     689                                                break;
     690                                        } );
     691                        }
     692                       
     693                        pthread_cleanup_pop(0);
     694                        CHECK_FCT_DO( pthread_rwlock_unlock( &rt_out_lock ), goto fatal_error );
     695                       
     696                        /* If an error occurred, skip to the next message */
     697                        if (!msg)
     698                                continue;
     699                }
     700               
     701                /* Order the candidate peers by score attributed by the callbacks */
     702                CHECK_FCT_DO( fd_rtd_candidate_reorder(candidates), goto fatal_error );
     703               
     704                /* Save the routing information in the message */
     705                CHECK_FCT_DO( fd_msg_rt_associate ( msg, &rtd ), goto fatal_error );
     706               
     707                /* Now try sending the message */
     708                for (li = candidates->prev; li != candidates; li = li->prev) {
     709                        struct fd_peer * peer;
     710                       
     711                        c = (struct rtd_candidate *) li;
     712                       
     713                        /* Stop when we have reached the end of valid candidates */
     714                        if (c->score < 0)
     715                                break;
     716                       
     717                        /* Search for the peer */
     718                        CHECK_FCT_DO( fd_peer_getbyid( c->diamid, (void *)&peer ), goto fatal_error );
     719                       
     720                        if (peer && (peer->p_hdr.info.runtime.pir_state == STATE_OPEN)) {
     721                                /* Send to this one */
     722                                CHECK_FCT_DO( fd_out_send(&msg, NULL, peer), continue );
     723                                /* If the sending was successful */
     724                                break;
     725                        }
     726                }
     727               
     728                /* If the message has not been sent, return an error */
     729                if (msg) {
     730                        TRACE_DEBUG(INFO, "Could not send the following message, replying with UNABLE_TO_DELIVER");
     731                        fd_msg_dump_walk(INFO, msg);
     732                        return_error( msg, "DIAMETER_UNABLE_TO_DELIVER", "No suitable candidate to route the message to", NULL);
     733                }
    611734               
    612735                /* We're done with this message */
     736               
    613737        } while (1);
    614738       
     
    619743}
    620744
    621 
     745static pthread_t rt_out = (pthread_t)NULL;
     746static pthread_t rt_in  = (pthread_t)NULL;
    622747
    623748/* Initialize the routing module */
    624749int fd_rt_init(void)
    625750{
    626         TODO("Start the routing threads");
     751        CHECK_POSIX( pthread_create( &rt_out, NULL, routing_out_thr, NULL) );
     752        CHECK_POSIX( pthread_create( &rt_in,  NULL, routing_in_thr,  NULL) );
    627753       
    628754        /* Later: TODO("Set the thresholds for the IN and OUT queues to create more routing threads as needed"); */
    629         return ENOTSUP;
     755        return 0;
    630756}
    631757
     
    633759int fd_rt_fini(void)
    634760{
    635         TODO("Stop the routing threads");
    636         return ENOTSUP;
    637 }
    638 
    639 
    640 
     761        CHECK_FCT_DO( fd_thr_term(&rt_in ), /* continue */);
     762        CHECK_FCT_DO( fd_thr_term(&rt_out), /* continue */);
     763        return 0;
     764}
     765
     766
     767
  • include/freeDiameter/libfreeDiameter.h

    r87 r88  
    16321632void fd_rtd_candidate_del(struct rt_data * rtd, char * peerid, size_t sz /* if !0, peerid does not need to be \0 terminated */);
    16331633
     1634/* Extract the list of valid candidates, and initialize their scores to 0 */
     1635void fd_rtd_candidate_extract(struct rt_data * rtd, struct fd_list ** candidates);
     1636
    16341637/* If a peer returned a protocol error for this message, save it so that we don't try to send it there again */
    16351638int  fd_rtd_error_add(struct rt_data * rtd, char * sentto, uint8_t * origin, size_t originsz, uint32_t rcode);
    1636 
    1637 /* Extract the list of valid candidates, and initialize their scores to 0 */
    1638 void fd_rtd_candidate_extract(struct rt_data * rtd, struct fd_list ** candidates);
    16391639
    16401640/* The extracted list items have the following structure: */
Note: See TracChangeset for help on using the changeset viewer.