示例#1
0
Status_t
sa_SMInfoRecord(Mai_t *maip, sa_cntxt_t* sa_cntxt) {
	uint32_t	records;
    uint16_t    attribOffset;

	IB_ENTER("sa_SMInfoRecord", maip, 0, 0, 0);

//
//	Assume failure.
//
	records = 0;

//
//	Check the method.  If this is a template lookup, then call the regular
//	GetTable(*) template lookup routine.
//
	switch (maip->base.method) {
	case SA_CM_GET:
		INCREMENT_COUNTER(smCounterSaRxGetSmInfoRecord);
		(void)sa_SMInfoRecord_GetTable(maip, &records);
		break;
	case SA_CM_GETTABLE:
		INCREMENT_COUNTER(smCounterSaRxGetTblSmInfoRecord);
		(void)sa_SMInfoRecord_GetTable(maip, &records);
		break;
    default:
		maip->base.status = MAD_STATUS_BAD_METHOD;
		(void)sa_send_reply(maip, sa_cntxt);
		IB_LOG_WARN("sa_SMInfoRecord: invalid METHOD:", maip->base.method);
		IB_EXIT("sa_SMInfoRecord", VSTATUS_OK);
		return(VSTATUS_OK);
        break;
	}

//
//	Determine reply status
//
	if (records == 0) {
		maip->base.status = MAD_STATUS_SA_NO_RECORDS;
	} else if ((maip->base.method == SA_CM_GET) && (records != 1)) {
        IB_LOG_WARN("sa_SMInfoRecord: too many records for SA_CM_GET:", records);
        records = 0;
		maip->base.status = MAD_STATUS_SA_TOO_MANY_RECS;
	} else {
		maip->base.status = MAD_STATUS_OK;
	}
    attribOffset =  sizeof(STL_SMINFO_RECORD) + Calculate_Padding(sizeof(STL_SMINFO_RECORD));
    /* setup attribute offset for possible RMPP transfer */
    sa_cntxt->attribLen = attribOffset;
	sa_cntxt_data( sa_cntxt, sa_data, records * attribOffset);
	(void)sa_send_reply(maip, sa_cntxt );

	IB_EXIT("sa_SMInfoRecord", VSTATUS_OK);
	return(VSTATUS_OK);
}
示例#2
0
/*
 * Age context and do resends for those that timed out
 */
void sa_cntxt_age(void)
{
	sa_cntxt_t* sa_cntxt = NULL ;
	sa_cntxt_t*	tout_cntxt ;
    int i;
	Status_t	status;

    if ((status = vs_lock(&sa_cntxt_lock)) != VSTATUS_OK) {
        IB_LOG_ERRORRC("sa_cntxt_age: Failed to lock SA context rc:", status);
    } else {
        vs_time_get( &timeLastAged );
        for (i=0; i<SA_CNTXT_HASH_TABLE_DEPTH; i++) {
            sa_cntxt = sa_hash[ i ];
            while( sa_cntxt ) {
                // Iterate before the pointers are destroyed ;
                tout_cntxt = sa_cntxt ;
                sa_cntxt = sa_cntxt->next ;

                // Though list is sorted, it does not hurt to 
                // do a simple comparison
                if( timeLastAged - tout_cntxt->tstamp > tout_cntxt->RespTimeout) { // used to be VTIMER_1S
                    // Timeout this entry
                    sa_cntxt_delete_entry( sa_hash[ i ], tout_cntxt );
                    sa_cntxt_insert_head( sa_hash[ i ], tout_cntxt );
                    // Touch the entry
                    tout_cntxt->tstamp = timeLastAged ;
                    // Call timeout
                    tout_cntxt->sendFd = fd_sa_w;       // use sa writer mai handle for restransmits
                    if (tout_cntxt->method == SA_CM_GETMULTI && tout_cntxt->reqInProg) {
                        // resend the getMulti request ACK
                        sa_getMulti_resend_ack(tout_cntxt);
                        /* if need to release the context.  Call local safe release */
                        if( tout_cntxt->retries > sm_config.max_retries ) cntxt_release(sa_cntxt);
                    } else {
                        // resend the reply
                        sa_send_reply( NULL, tout_cntxt );
                        if( tout_cntxt->retries > sm_config.max_retries ) {
                            /* need to release the context.  Call local safe release */
                            cntxt_release(tout_cntxt);
                        }
                    }
                }
            }
        }
        if ((status = vs_unlock(&sa_cntxt_lock)) != VSTATUS_OK) {
            IB_LOG_ERRORRC("cs_cntxt_age: Failed to unlock SA context rc:", status);
        }
    }
}
示例#3
0
void
sa_main_reader(uint32_t argc, uint8_t ** argv) {
	Status_t	status;
	Mai_t		in_mad;
	Filter_t	filter;
	sa_cntxt_t	*sa_cntxt=NULL;
	uint64_t	now, delta, max_delta;
	int			tries=0, retry=0;
    uint64_t    reqTimeToLive=0;
    SAContextGet_t  cntxGetStatus=0;
    int         numContextBusy=0;

	IB_ENTER("sa_main_reader", 0, 0, 0, 0);

	sa_main_reader_exit = 0;
    
    /*
     *	Create the SubnAdm(*) MAD filter for the SA thread.
     */
	SA_Filter_Init(&filter);
	filter.value.mclass = MAD_CV_SUBN_ADM;
	filter.mask.mclass = 0xff;
	filter.value.method = 0x00;
	filter.mask.method = 0x80;
	filter.mai_filter_check_packet = sa_reader_filter;
	MAI_SET_FILTER_NAME (&filter, "SA Reader");

	if (mai_filter_create(fd_sa, &filter, VFILTER_SHARE) != VSTATUS_OK) {
		IB_LOG_ERROR0("sa_main_reader: can't create SubnAdm(*) filter");
		(void)vs_thread_exit(&sm_threads[SM_THREAD_SA_READER].handle);
	}

    timeMftLastUpdated = 0;
    /* 
     * calculate request time to live on queue
     * ~ 3.2secs for defaults: sa_packetLifetime=18 and sa_respTimeValue=18 
     */
    reqTimeToLive = 4ull * ( (2*(1 << sm_config.sa_packet_lifetime_n2)) + (1 << sm_config.sa_resp_time_n2) ); 
	while (1) {
		status = mai_recv(fd_sa, &in_mad, VTIMER_1S/4);

        if (sa_main_reader_exit == 1){
#ifdef __VXWORKS__
            ESM_LOG_ESMINFO("sa_main_reader: exiting OK.", 0);
#endif
            break;
        }
        /* don't process messages if not master SM or still doing first sweep */
		if ((sm_state != SM_STATE_MASTER) ||
		    (topology_passcount < 1)) {
            continue;
        }

		/* 
         * If the mai layer shuts down we end up in this infinite loop here.
		 * This may happen on initialization
         */
		if( status != VSTATUS_OK ){
            if (status != VSTATUS_TIMEOUT)
                IB_LOG_ERRORRC("sa_main_reader: error on mai_recv rc:", status);
        } else {
            /* 
             * Drop new requests that have been sitting on SA reader queue for too long 
             */
            if (in_mad.intime) {
				/* PR 110586 - On some RHEL 5 systems, we've seen  weird issues with gettimeofday() [used by vs_time_get()]
				 * where once in a while the time difference calculated from successive calls to gettimeofday()
				 * results in a negative value. Due to this, we might actually consider a request stale even if
				 * its not. Work around this by making calls to gettimeofday() till it returns us some
				 * sane values. Just to be extra cautious, bound the retries so that we don't get stuck in the loop.  
				 */
				tries = 0;
				/* Along with negative values also check for unreasonably high values of delta*/
				max_delta = 30*reqTimeToLive;
				do {
					vs_time_get( &now );
					delta = now - in_mad.intime;
					tries++;
					
					if ((now < in_mad.intime) || (delta > max_delta)) {
						vs_thread_sleep(1);
						retry = 1;
					} else {
						retry = 0;
					}	
				} while (retry && tries < 20);

                if (delta > reqTimeToLive) {
					INCREMENT_COUNTER(smCounterSaDroppedRequests);
                    if (smDebugPerf || saDebugPerf) {
                        IB_LOG_INFINI_INFO_FMT( "sa_main_reader",
                               "Dropping stale %s[%s] request from LID[0x%x], TID="FMT_U64"; On queue for %d.%d seconds.", 
                               sa_getMethodText((int)in_mad.base.method), sa_getAidName((int)in_mad.base.aid), in_mad.addrInfo.slid, 
                               in_mad.base.tid, (int)(delta/1000000), (int)((delta - delta/1000000*1000000))/1000);
                    }
                    /* drop the request without returning a response; sender will retry */
                    continue;
                }
            }
            /* 
             * get a context to process request; sa_cntxt can be:
             *   1. NULL if resources are scarce
             *   2. NULL if request is dup of existing request
             *   3. in progress getMulti request context
             *   4. New context for a brand new request 
             */
            cntxGetStatus = sa_cntxt_get( &in_mad, (void *)&sa_cntxt );
            if (cntxGetStatus == ContextAllocated) {
				/* process the new request */
				sa_process_mad( &in_mad, sa_cntxt );
				/* 
				 * This may not necessarily release context based on if someone else has reserved it
				 */
				if(sa_cntxt) sa_cntxt_release( sa_cntxt );
			} else if (cntxGetStatus == ContextExist) {
				INCREMENT_COUNTER(smCounterSaDuplicateRequests);
				/* this is a duplicate request */
				if (saDebugPerf || saDebugRmpp) {
					IB_LOG_INFINI_INFO_FMT( "sa_main_reader",
					       "SA_READER received duplicate %s[%s] from LID [0x%x] with TID ["FMT_U64"] ", 
					       sa_getMethodText((int)in_mad.base.method), sa_getAidName((int)in_mad.base.aid),in_mad.addrInfo.slid, in_mad.base.tid);
				}
            } else if (cntxGetStatus == ContextNotAvailable) {
				INCREMENT_COUNTER(smCounterSaContextNotAvailable);
                /* we are swamped, return BUSY to caller */
                if (saDebugPerf || saDebugRmpp) { /* log msg before send changes method and lids */
                    IB_LOG_INFINI_INFO_FMT( "sa_main_reader",
                           "NO CONTEXT AVAILABLE, returning MAD_STATUS_BUSY to %s[%s] request from LID [0x%x], TID ["FMT_U64"]!",
                           sa_getMethodText((int)in_mad.base.method), sa_getAidName((int)in_mad.base.aid), in_mad.addrInfo.slid, in_mad.base.tid);
                }
                in_mad.base.status = MAD_STATUS_BUSY;
                sa_send_reply( &in_mad, sa_cntxt );
                if ((++numContextBusy % sa_max_cntxt) == 0) {
                    IB_LOG_INFINI_INFO_FMT( "sa_main_reader",
                           "Had to drop %d SA requests since start due to no available contexts",
                           numContextBusy);
                }
            } else if (cntxGetStatus == ContextExistGetMulti) {
                /* continue processing the getMulti request */
                sa_process_getmulti( &in_mad, sa_cntxt );
                if(sa_cntxt) sa_cntxt_release( sa_cntxt );
            } else {
                IB_LOG_WARN("sa_main_reader: Invalid sa_cntxt_get return code:", cntxGetStatus);
            }
        }

        /* 
         * signal sm_top to reprogram the MFTs
         * Wait one second to allow mcmember requests to accumulate before asking
         */
        vs_time_get( &now );
        if (sa_mft_reprog && timeMftLastUpdated == 0) {
            timeMftLastUpdated = now;
        } else if (sa_mft_reprog && (now - timeMftLastUpdated) > VTIMER_1S) {
            topology_wakeup_time = 0ull;
            if ((status = vs_lock(&sa_lock)) != VSTATUS_OK) {
                IB_LOG_ERRORRC("sa_main_reader: Failed to lock sa_lock rc:", status);
            } else {
                sm_McGroups_Need_Prog = 1;      /* tells Topoloy thread that MFT reprogramming is needed */
                (void)vs_unlock(&sa_lock);
            }
            sm_trigger_sweep(SM_SWEEP_REASON_MCMEMBER);
            /* clear the indicators */
            timeMftLastUpdated = 0;
            sa_mft_reprog = 0;
        }
	}
    /* cleanup before exit, but allow some time for the other threads to flush out first */
    (void)vs_thread_sleep(VTIMER_1S);     
    (void)sa_SubscriberDelete();
    (void)sa_ServiceRecDelete();
    (void)sa_McGroupDelete();
	if (mai_filter_delete(fd_sa, &filter, VFILTER_SHARE) != VSTATUS_OK) {
		IB_LOG_ERROR0("sa_main_reader: can't delete SubnAdm(*) filter");
	}
	//IB_LOG_INFINI_INFO0("sa_main_reader thread: Exiting OK");
}
示例#4
0
Status_t
sa_ClassPortInfo(Mai_t *maip, sa_cntxt_t* sa_cntxt) {

	uint16_t				attribOffset;
        union {
		STL_CLASS_PORT_INFO		stl_version;
		IB_CLASS_PORT_INFO		ib_version;
	} myCPI;

	IB_ENTER("sa_ClassPortInfo", maip, 0, 0, 0);

//
//	Check the method.  For ClassPortInfo, you can only do a Get().
//
	if (maip->base.method == SA_CM_GET) {
		INCREMENT_COUNTER(smCounterSaRxGetClassPortInfo);
                if (maip->base.cversion == SA_MAD_CVERSION) {
			memset(&myCPI.ib_version,0,sizeof(IB_CLASS_PORT_INFO));
			myCPI.ib_version.BaseVersion = saClassPortInfo.BaseVersion;
			myCPI.ib_version.ClassVersion = saClassPortInfo.ClassVersion;
			myCPI.ib_version.CapMask =
				STL_CLASS_PORT_CAPMASK_CM2 |
				STL_SA_CAPABILITY_MULTICAST_SUPPORT |
				STL_SA_CAPABILITY_MULTIPATH_SUPPORT |
				STL_SA_CAPABILITY_PORTINFO_CAPMASK_MATCH |
				STL_SA_CAPABILITY_PA_SERVICES_SUPPORT;
			myCPI.ib_version.u1.s.CapMask2 =
				STL_SA_CAPABILITY2_QOS_SUPPORT |
				STL_SA_CAPABILITY2_MFTTOP_SUPPORT |
				STL_SA_CAPABILITY2_FULL_PORTINFO |
				STL_SA_CAPABILITY2_EXT_SUPPORT;
			myCPI.ib_version.u1.s.RespTimeValue = saClassPortInfo.u1.s.RespTimeValue;
			myCPI.ib_version.u3.s.RedirectQP = saClassPortInfo.u3.s.RedirectQP;
			myCPI.ib_version.u5.s.TrapHopLimit = saClassPortInfo.u5.s.TrapHopLimit;
			myCPI.ib_version.u5.s.TrapQP = saClassPortInfo.u5.s.TrapQP;
			BSWAP_IB_CLASS_PORT_INFO(&myCPI.ib_version);

			attribOffset = sizeof(IB_CLASS_PORT_INFO) + 
							Calculate_Padding(sizeof(IB_CLASS_PORT_INFO));
			sa_cntxt_data( sa_cntxt, &myCPI.ib_version, attribOffset);
			sa_cntxt->attribLen = attribOffset;
			maip->base.status = MAD_STATUS_OK;
		} else if (maip->base.cversion >= STL_SM_CLASS_VERSION) {
			myCPI.stl_version = saClassPortInfo;
			BSWAP_STL_CLASS_PORT_INFO(&myCPI.stl_version);

			attribOffset = sizeof(STL_CLASS_PORT_INFO) + 
							Calculate_Padding(sizeof(STL_CLASS_PORT_INFO));

			sa_cntxt_data( sa_cntxt, &myCPI.stl_version, attribOffset);
			sa_cntxt->attribLen = attribOffset;
		maip->base.status = MAD_STATUS_OK;
		} else {
			maip->base.status = MAD_STATUS_BAD_METHOD;
		}
	} else {
		maip->base.status = MAD_STATUS_BAD_METHOD;
	}
	(void)sa_send_reply(maip, sa_cntxt);

	IB_EXIT("sa_ClassPortInfo", VSTATUS_OK);
	return(VSTATUS_OK);
}