/* Listener client attaches to a stream */ bool openavbEptSrvrAttachStream(int h, AVBStreamID_t *streamID, openavbSrpLsnrDeclSubtype_t ld) { openavbRC rc = OPENAVB_SUCCESS; static U8 emptyMAC[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; static AVBTSpec_t emptytSpec = {0, 0}; AVB_TRACE_ENTRY(AVB_TRACE_ENDPOINT); clientStream_t *ps = findStream(streamID); if (ps && ps->clientHandle != h) { AVB_LOGF_ERROR("Error attaching listener: multiple clients for stream %d", streamID->uniqueID); AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT); return FALSE; } if (!ps) { ps = addStream(h, streamID); if (!ps) { AVB_LOGF_ERROR("Error attaching listener: unable to add client stream %d", streamID->uniqueID); AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT); return FALSE; } ps->role = clientListener; } if(x_cfg.noSrp) { // we are operating in a mode supporting preconfigured streams; SRP is not in use, if(ld == openavbSrp_LDSt_Interest) { // As a proxy for SRP, which would normally make this call after confirming // availability of the stream, call the callback from here strmRegCb((void*)ps, openavbSrp_AtTyp_TalkerAdvertise, emptyMAC, // a flag to listener to read info from configuration file &emptytSpec, MAX_AVB_SR_CLASSES, // srClass - value doesn't matter because openavbEptSrvrNotifyLstnrOfSrpCb() throws it away 1, // accumLatency NULL); // *failInfo } } else { // Normal SRP Operation so pass to SRP rc = openavbSrpAttachStream((void*)ps, streamID, ld); if (!IS_OPENAVB_SUCCESS(rc)) delStream(ps); } openavbEndPtLogAllStaticStreams(); AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT); return IS_OPENAVB_SUCCESS(rc); }
static inline bool listenerDoStream(tl_state_t *pTLState) { AVB_TRACE_ENTRY(AVB_TRACE_TL); if (!pTLState) { AVB_LOG_ERROR("Invalid TLState"); AVB_TRACE_EXIT(AVB_TRACE_TL); return FALSE; } openavb_tl_cfg_t *pCfg = &pTLState->cfg; listener_data_t *pListenerData = pTLState->pPvtListenerData; bool bRet = FALSE; if (pTLState->bStreaming) { U64 nowNS; pListenerData->nReportCalls++; // Try to receive a frame if (IS_OPENAVB_SUCCESS(openavbAvtpRx(pListenerData->avtpHandle))) { pListenerData->nReportFrames++; } CLOCK_GETTIME64(OPENAVB_TIMER_CLOCK, &nowNS); if (pCfg->report_seconds > 0) { if (nowNS > pListenerData->nextReportNS) { listenerShowStats(pListenerData, pTLState); openavbListenerAddStat(pTLState, TL_STAT_RX_CALLS, pListenerData->nReportCalls); openavbListenerAddStat(pTLState, TL_STAT_RX_FRAMES, pListenerData->nReportFrames); pListenerData->nReportCalls = 0; pListenerData->nReportFrames = 0; pListenerData->nextReportNS += (pCfg->report_seconds * NANOSECONDS_PER_SECOND); } } else if (pCfg->report_frames > 0 && pListenerData->nReportFrames != pListenerData->lastReportFrames) { if (pListenerData->nReportFrames % pCfg->report_frames == 1) { listenerShowStats(pListenerData, pTLState); pListenerData->lastReportFrames = pListenerData->nReportFrames; } } if (nowNS > pListenerData->nextSecondNS) { pListenerData->nextSecondNS += NANOSECONDS_PER_SECOND; bRet = TRUE; } } else { SLEEP_MSEC(1); bRet = TRUE; } AVB_TRACE_EXIT(AVB_TRACE_TL); return bRet; }
bool x_listenerDetach(clientStream_t *ps) { AVB_TRACE_ENTRY(AVB_TRACE_ENDPOINT); openavbRC rc = OPENAVB_SUCCESS; if(!x_cfg.noSrp) { // Pass to SRP rc = openavbSrpDetachStream(&ps->streamID); } // remove record delStream(ps); openavbEndPtLogAllStaticStreams(); AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT); return IS_OPENAVB_SUCCESS(rc); }
/************************************************************* * MAAP Restart - our destination MAC has been changed. * * This is a clunky way to handle it - but it works, and this code * won't be called often. (MAAP sends probes before settling on an * address, so only a buggy or malicious peer should send us down this * path.) * * A better way to handle this would require SRP and the * talkers/listeners to look at destination addresses (in addition * to StreamID and talker/listener declaration) and explicitly handle * destination address changes. */ static void maapRestartCallback(void* handle, struct ether_addr *addr) { AVB_TRACE_ENTRY(AVB_TRACE_ENDPOINT); static clientStream_t* ps; openavbRC rc; ps = findStreamMaap(handle); AVB_LOGF_STATUS("MAAP restart callback: handle=%p, stream=%p", handle, ps); if (ps) { memcpy(ps->destAddr, addr->ether_addr_octet, ETH_ALEN); // Pretend that our listeners went away strmAttachCb(ps, (openavbSrpLsnrDeclSubtype_t)0); if(!x_cfg.noSrp) { // Remove the old registration with SRP openavbSrpDeregisterStream(&ps->streamID); // Re-register with the new address rc = openavbSrpRegisterStream((void*)ps, &ps->streamID, ps->destAddr, &ps->tSpec, ps->srClass, ps->srRank, ps->latency); } else { rc = OPENAVB_SUCCESS; } if (!IS_OPENAVB_SUCCESS(rc)) { AVB_LOG_ERROR("MAAP restart: failed to re-register talker stream"); } } AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT); }
/************************************************************* * * Internal function to cleanup streams * */ bool x_talkerDeregister(clientStream_t *ps) { AVB_TRACE_ENTRY(AVB_TRACE_ENDPOINT); openavbRC rc = OPENAVB_SUCCESS; if(!x_cfg.noSrp) { // Pass to SRP rc = openavbSrpDeregisterStream(&ps->streamID); } // Remove QMgr entry for stream if (ps->fwmark != INVALID_FWMARK) { openavbQmgrRemoveStream(ps->fwmark); ps->fwmark = INVALID_FWMARK; } // Release MAAP address allocation if (ps->hndMaap) { openavbMaapRelease(ps->hndMaap); ps->hndMaap = NULL; } // Finish Shaping if (ps->hndShaper) { openavbShaperRelease(ps->hndShaper); ps->hndShaper = NULL; } // remove record delStream(ps); openavbEndPtLogAllStaticStreams(); AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT); return IS_OPENAVB_SUCCESS(rc); }
static inline bool talkerDoStream(tl_state_t *pTLState) { AVB_TRACE_ENTRY(AVB_TRACE_TL); if (!pTLState) { AVB_LOG_ERROR("Invalid TLState"); AVB_TRACE_EXIT(AVB_TRACE_TL); return FALSE; } openavb_tl_cfg_t *pCfg = &pTLState->cfg; talker_data_t *pTalkerData = pTLState->pPvtTalkerData; bool bRet = FALSE; if (pTLState->bStreaming) { U64 nowNS; if (!pCfg->tx_blocking_in_intf) { // sleep until the next interval SLEEP_UNTIL_NSEC(pTalkerData->nextCycleNS); //AVB_DBG_INTERVAL(8000, TRUE); // send the frames for this interval int i; for (i = pTalkerData->wakeFrames; i > 0; i--) { if (IS_OPENAVB_SUCCESS(openavbAvtpTx(pTalkerData->avtpHandle, i == 1, pCfg->tx_blocking_in_intf))) pTalkerData->cntFrames++; else break; } } else { // Interface module block option if (IS_OPENAVB_SUCCESS(openavbAvtpTx(pTalkerData->avtpHandle, TRUE, pCfg->tx_blocking_in_intf))) pTalkerData->cntFrames++; } if (pTalkerData->cntWakes++ % pTalkerData->wakeRate == 0) { // time to service the endpoint IPC bRet = TRUE; } CLOCK_GETTIME64(OPENAVB_TIMER_CLOCK, &nowNS); if (pCfg->report_seconds > 0) { if (nowNS > pTalkerData->nextReportNS) { S32 late = pTalkerData->wakesPerReport - pTalkerData->cntWakes; U64 bytes = openavbAvtpBytes(pTalkerData->avtpHandle); if (late < 0) late = 0; U32 txbuf = openavbAvtpTxBufferLevel(pTalkerData->avtpHandle); U32 mqbuf = openavbMediaQCountItems(pTLState->pMediaQ, TRUE); AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, FALSE, "TX UID:%d, ", LOG_RT_DATATYPE_U16, &pTalkerData->streamID.uniqueID); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "calls=%ld, ", LOG_RT_DATATYPE_U32, &pTalkerData->cntWakes); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "frames=%ld, ", LOG_RT_DATATYPE_U32, &pTalkerData->cntFrames); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "late=%d, ", LOG_RT_DATATYPE_U32, &late); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "bytes=%lld, ", LOG_RT_DATATYPE_U64, &bytes); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "txbuf=%d, ", LOG_RT_DATATYPE_U32, &txbuf); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, LOG_RT_END, "mqbuf=%d, ", LOG_RT_DATATYPE_U32, &mqbuf); openavbTalkerAddStat(pTLState, TL_STAT_TX_CALLS, pTalkerData->cntWakes); openavbTalkerAddStat(pTLState, TL_STAT_TX_FRAMES, pTalkerData->cntFrames); openavbTalkerAddStat(pTLState, TL_STAT_TX_LATE, late); openavbTalkerAddStat(pTLState, TL_STAT_TX_BYTES, bytes); pTalkerData->cntFrames = 0; pTalkerData->cntWakes = 0; pTalkerData->nextReportNS = nowNS + (pCfg->report_seconds * NANOSECONDS_PER_SECOND); } } if (nowNS > pTalkerData->nextSecondNS) { pTalkerData->nextSecondNS += NANOSECONDS_PER_SECOND; bRet = TRUE; } if (!pCfg->tx_blocking_in_intf) { pTalkerData->nextCycleNS += pTalkerData->intervalNS; if ((pTalkerData->nextCycleNS + (pCfg->max_transmit_deficit_usec * 1000)) < nowNS) { // Hit max deficit time. Something must be wrong. Reset the cycle timer. // Align clock : allows for some performance gain nowNS = ((nowNS + (pTalkerData->intervalNS)) / pTalkerData->intervalNS) * pTalkerData->intervalNS; pTalkerData->nextCycleNS = nowNS + pTalkerData->intervalNS; } } } else { SLEEP(1); // time to service the endpoint IPC bRet = TRUE; } AVB_TRACE_EXIT(AVB_TRACE_TL); return bRet; }
static inline bool listenerDoStream(tl_state_t *pTLState) { AVB_TRACE_ENTRY(AVB_TRACE_TL); if (!pTLState) { AVB_LOG_ERROR("Invalid TLState"); AVB_TRACE_EXIT(AVB_TRACE_TL); return FALSE; } openavb_tl_cfg_t *pCfg = &pTLState->cfg; listener_data_t *pListenerData = pTLState->pPvtListenerData; bool bRet = FALSE; if (pTLState->bStreaming) { U64 nowNS; pListenerData->nReportCalls++; // Try to receive a frame if (IS_OPENAVB_SUCCESS(openavbAvtpRx(pListenerData->avtpHandle))) { pListenerData->nReportFrames++; } CLOCK_GETTIME64(OPENAVB_TIMER_CLOCK, &nowNS); if (pCfg->report_seconds > 0) { if (nowNS > pListenerData->nextReportNS) { U64 lost = openavbAvtpLost(pListenerData->avtpHandle); U64 bytes = openavbAvtpBytes(pListenerData->avtpHandle); U32 rxbuf = openavbAvtpRxBufferLevel(pListenerData->avtpHandle); U32 mqbuf = openavbMediaQCountItems(pTLState->pMediaQ, TRUE); U32 mqrdy = openavbMediaQCountItems(pTLState->pMediaQ, FALSE); AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, FALSE, "RX UID:%d, ", LOG_RT_DATATYPE_U16, &pListenerData->streamID.uniqueID); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "calls=%ld, ", LOG_RT_DATATYPE_U32, &pListenerData->nReportCalls); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "frames=%ld, ", LOG_RT_DATATYPE_U32, &pListenerData->nReportFrames); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "lost=%lld, ", LOG_RT_DATATYPE_U64, &lost); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "bytes=%lld, ", LOG_RT_DATATYPE_U64, &bytes); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "rxbuf=%d, ", LOG_RT_DATATYPE_U32, &rxbuf); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "mqbuf=%d, ", LOG_RT_DATATYPE_U32, &mqbuf); AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, LOG_RT_END, "mqrdy=%d", LOG_RT_DATATYPE_U32, &mqrdy); openavbListenerAddStat(pTLState, TL_STAT_RX_CALLS, pListenerData->nReportCalls); openavbListenerAddStat(pTLState, TL_STAT_RX_FRAMES, pListenerData->nReportFrames); openavbListenerAddStat(pTLState, TL_STAT_RX_LOST, lost); openavbListenerAddStat(pTLState, TL_STAT_RX_BYTES, bytes); pListenerData->nReportCalls = 0; pListenerData->nReportFrames = 0; pListenerData->nextReportNS += (pCfg->report_seconds * NANOSECONDS_PER_SECOND); } } if (nowNS > pListenerData->nextSecondNS) { pListenerData->nextSecondNS += NANOSECONDS_PER_SECOND; bRet = TRUE; } } else { SLEEP(1); bRet = TRUE; } AVB_TRACE_EXIT(AVB_TRACE_TL); return bRet; }
void openavbAcmpSMController_txCommand(U8 messageType, openavb_acmp_ACMPCommandResponse_t *command, bool retry) { AVB_TRACE_ENTRY(AVB_TRACE_ACMP); openavb_list_node_t node = NULL; openavbRC rc = openavbAcmpMessageSend(messageType, command, OPENAVB_ACMP_STATUS_SUCCESS); if (IS_OPENAVB_SUCCESS(rc)) { if (!retry) { node = openavbListNew(openavbAcmpSMControllerVars.inflight, sizeof(openavb_acmp_InflightCommand_t)); if (node) { openavb_acmp_InflightCommand_t *pInFlightCommand = openavbListData(node); if (pInFlightCommand) { memcpy(&pInFlightCommand->command, command, sizeof(pInFlightCommand->command)); pInFlightCommand->command.message_type = messageType; pInFlightCommand->retried = FALSE; pInFlightCommand->original_sequence_id = command->sequence_id; // AVDECC_TODO - is this correct? CLOCK_GETTIME(OPENAVB_CLOCK_REALTIME, &pInFlightCommand->timer); switch (messageType) { case OPENAVB_ACMP_MESSAGE_TYPE_GET_TX_STATE_RESPONSE: openavbTimeTimespecAddUsec(&pInFlightCommand->timer, OPENAVB_ACMP_COMMAND_TIMEOUT_GET_TX_STATE_COMMAND * MICROSECONDS_PER_MSEC); break; case OPENAVB_ACMP_MESSAGE_TYPE_CONNECT_RX_RESPONSE: openavbTimeTimespecAddUsec(&pInFlightCommand->timer, OPENAVB_ACMP_COMMAND_TIMEOUT_CONNECT_RX_COMMAND * MICROSECONDS_PER_MSEC); break; case OPENAVB_ACMP_MESSAGE_TYPE_DISCONNECT_RX_RESPONSE: openavbTimeTimespecAddUsec(&pInFlightCommand->timer, OPENAVB_ACMP_COMMAND_TIMEOUT_DISCONNECT_RX_COMMAND * MICROSECONDS_PER_MSEC); break; case OPENAVB_ACMP_MESSAGE_TYPE_GET_RX_STATE_RESPONSE: openavbTimeTimespecAddUsec(&pInFlightCommand->timer, OPENAVB_ACMP_COMMAND_TIMEOUT_GET_RX_STATE_COMMAND * MICROSECONDS_PER_MSEC); break; case OPENAVB_ACMP_MESSAGE_TYPE_GET_TX_CONNECTION_RESPONSE: openavbTimeTimespecAddUsec(&pInFlightCommand->timer, OPENAVB_ACMP_COMMAND_TIMEOUT_GET_TX_CONNECTION_COMMAND * MICROSECONDS_PER_MSEC); break; default: AVB_LOGF_ERROR("Unsupported command %u in openavbAcmpSMController_txCommand", messageType); openavbTimeTimespecAddUsec(&pInFlightCommand->timer, OPENAVB_ACMP_COMMAND_TIMEOUT_CONNECT_RX_COMMAND * MICROSECONDS_PER_MSEC); break; } } } } else { // Retry case node = openavbAcmpSMController_findInflightNodeFromCommand(command); if (node) { openavb_acmp_InflightCommand_t *pInFlightCommand = openavbListData(node); if (pInFlightCommand) { pInFlightCommand->retried = TRUE; CLOCK_GETTIME(OPENAVB_CLOCK_REALTIME, &pInFlightCommand->timer); switch (messageType) { case OPENAVB_ACMP_MESSAGE_TYPE_GET_TX_STATE_RESPONSE: openavbTimeTimespecAddUsec(&pInFlightCommand->timer, OPENAVB_ACMP_COMMAND_TIMEOUT_GET_TX_STATE_COMMAND * MICROSECONDS_PER_MSEC); break; case OPENAVB_ACMP_MESSAGE_TYPE_CONNECT_RX_RESPONSE: openavbTimeTimespecAddUsec(&pInFlightCommand->timer, OPENAVB_ACMP_COMMAND_TIMEOUT_CONNECT_RX_COMMAND * MICROSECONDS_PER_MSEC); break; case OPENAVB_ACMP_MESSAGE_TYPE_DISCONNECT_RX_RESPONSE: openavbTimeTimespecAddUsec(&pInFlightCommand->timer, OPENAVB_ACMP_COMMAND_TIMEOUT_DISCONNECT_RX_COMMAND * MICROSECONDS_PER_MSEC); break; case OPENAVB_ACMP_MESSAGE_TYPE_GET_RX_STATE_RESPONSE: openavbTimeTimespecAddUsec(&pInFlightCommand->timer, OPENAVB_ACMP_COMMAND_TIMEOUT_GET_RX_STATE_COMMAND * MICROSECONDS_PER_MSEC); break; case OPENAVB_ACMP_MESSAGE_TYPE_GET_TX_CONNECTION_RESPONSE: openavbTimeTimespecAddUsec(&pInFlightCommand->timer, OPENAVB_ACMP_COMMAND_TIMEOUT_GET_TX_CONNECTION_COMMAND * MICROSECONDS_PER_MSEC); break; default: AVB_LOGF_ERROR("Unsupported command %u in openavbAcmpSMController_txCommand", messageType); openavbTimeTimespecAddUsec(&pInFlightCommand->timer, OPENAVB_ACMP_COMMAND_TIMEOUT_CONNECT_RX_COMMAND * MICROSECONDS_PER_MSEC); break; } } } } } else { // Failed to send command openavbAcmpMessageSend(messageType, command, OPENAVB_ACMP_STATUS_COULD_NOT_SEND_MESSAGE); if (retry) { node = openavbAcmpSMController_findInflightNodeFromCommand(command); if (node) { openavbListDelete(openavbAcmpSMControllerVars.inflight, node); } } } AVB_TRACE_EXIT(AVB_TRACE_ACMP); }
/* Talker client registers a stream */ bool openavbEptSrvrRegisterStream(int h, AVBStreamID_t *streamID, U8 destAddr[], AVBTSpec_t *tSpec, U8 srClass, U8 srRank, U32 latency) { openavbRC rc = OPENAVB_SUCCESS; AVB_TRACE_ENTRY(AVB_TRACE_ENDPOINT); clientStream_t *ps = findStream(streamID); if (ps && ps->clientHandle != h) { AVB_LOGF_ERROR("Error registering talker; multiple clients for stream %d", streamID->uniqueID); AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT); return FALSE; } ps = addStream(h, streamID); if (!ps) { AVB_LOGF_ERROR("Error registering talker; unable to add client stream %d", streamID->uniqueID); AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT); return FALSE; } ps->role = clientTalker; ps->tSpec = *tSpec; ps->srClass = (SRClassIdx_t)srClass; ps->srRank = srRank; ps->latency = latency; ps->fwmark = INVALID_FWMARK; if (memcmp(ps->destAddr, destAddr, ETH_ALEN) == 0) { // no client-supplied address, use MAAP struct ether_addr addr; ps->hndMaap = openavbMaapAllocate(1, &addr); if (ps->hndMaap) { memcpy(ps->destAddr, addr.ether_addr_octet, ETH_ALEN); strmAttachCb((void*)ps, openavbSrp_LDSt_Stream_Info); // Inform talker about MAAP } else { AVB_LOG_ERROR("Error registering talker: MAAP failed to allocate MAC address"); AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT); delStream(ps); return FALSE; } } else { // client-supplied destination MAC address memcpy(ps->destAddr, destAddr, ETH_ALEN); ps->hndMaap = NULL; } // Do SRP talker register AVB_LOGF_DEBUG("REGISTER: ps=%p, streamID=%d, tspec=%d,%d, srClass=%d, srRank=%d, latency=%d, da="ETH_FORMAT"", ps, streamID->uniqueID, tSpec->maxFrameSize, tSpec->maxIntervalFrames, ps->srClass, ps->srRank, ps->latency, ETH_OCTETS(ps->destAddr)); if(x_cfg.noSrp) { // we are operating in a mode supporting preconfigured streams; SRP is not in use, // so, as a proxy for SRP, which would normally make this call after establishing // the stream, call the callback from here strmAttachCb((void*)ps, openavbSrp_LDSt_Ready); } else { // normal SRP operation rc = openavbSrpRegisterStream((void*)ps, &ps->streamID, ps->destAddr, &ps->tSpec, ps->srClass, ps->srRank, ps->latency); if (!IS_OPENAVB_SUCCESS(rc)) { if (ps->hndMaap) openavbMaapRelease(ps->hndMaap); delStream(ps); } } openavbEndPtLogAllStaticStreams(); AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT); return IS_OPENAVB_SUCCESS(rc); }
int avbEndpointLoop(void) { AVB_TRACE_ENTRY(AVB_TRACE_ENDPOINT); int retVal = -1; openavbRC rc = OPENAVB_SUCCESS; do { if (!x_cfg.bypassAsCapableCheck && (startPTP() < 0)) { // make sure ptp, a separate process, starts and is using the same interface as endpoint AVB_LOG_ERROR("PTP failed to start - Exiting"); break; } else if(x_cfg.bypassAsCapableCheck) { AVB_LOG_WARNING(" "); AVB_LOG_WARNING("Configuration 'gptp_asCapable_not_required = 1' is set."); AVB_LOG_WARNING("This configuration bypasses the requirement for gPTP"); AVB_LOG_WARNING("and openavb_gptp is not started automatically."); AVB_LOG_WARNING("An appropriate ptp MUST be started separately."); AVB_LOG_WARNING("Any network which does not use ptp to synchronize time"); AVB_LOG_WARNING("on each and every network device is NOT an AVB network."); AVB_LOG_WARNING("Such a network WILL NOT FUNCTION PROPERLY."); AVB_LOG_WARNING(" "); } x_streamList = NULL; if (!openavbQmgrInitialize(x_cfg.fqtss_mode, x_cfg.ifindex, x_cfg.ifname, x_cfg.mtu, x_cfg.link_kbit, x_cfg.nsr_kbit)) { AVB_LOG_ERROR("Failed to initialize QMgr"); break; } if (!openavbMaapInitialize(x_cfg.ifname, x_cfg.maapPort, &(x_cfg.maap_preferred), maapRestartCallback)) { AVB_LOG_ERROR("Failed to initialize MAAP"); openavbQmgrFinalize(); break; } if (!openavbShaperInitialize(x_cfg.ifname, x_cfg.shaperPort)) { AVB_LOG_ERROR("Failed to initialize Shaper"); openavbMaapFinalize(); openavbQmgrFinalize(); break; } if(!x_cfg.noSrp) { // Initialize SRP rc = openavbSrpInitialize(strmAttachCb, strmRegCb, x_cfg.ifname, x_cfg.link_kbit, x_cfg.bypassAsCapableCheck); } else { rc = OPENAVB_SUCCESS; AVB_LOG_WARNING(" "); AVB_LOG_WARNING("Configuration 'preconfigured = 1' is set."); AVB_LOG_WARNING("SRP is disabled. Streams MUST be configured manually"); AVB_LOG_WARNING("on each and every device in the network, without exception."); AVB_LOG_WARNING("AN AVB NETWORK WILL NOT FUNCTION AS EXPECTED UNLESS ALL"); AVB_LOG_WARNING("STREAMS ARE PROPERLY CONFIGURED ON ALL NETWORK DEVICES."); AVB_LOG_WARNING(" "); } if (!IS_OPENAVB_SUCCESS(rc)) { AVB_LOG_ERROR("Failed to initialize SRP"); openavbShaperFinalize(); openavbMaapFinalize(); openavbQmgrFinalize(); break; } if (openavbEndpointServerOpen()) { retVal = 0; while (endpointRunning) { openavbEptSrvrService(); } openavbEndpointServerClose(); } if(!x_cfg.noSrp) { // Shutdown SRP openavbSrpShutdown(); } openavbShaperFinalize(); openavbMaapFinalize(); openavbQmgrFinalize(); } while (0); if (!x_cfg.bypassAsCapableCheck && (stopPTP() < 0)) { AVB_LOG_WARNING("Failed to execute PTP stop command: killall -s SIGINT openavb_gptp"); } AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT); return retVal; }
/* SRP tells us about a listener peer (Listener Ready or Failed) */ openavbRC strmAttachCb(void* pv, openavbSrpLsnrDeclSubtype_t lsnrDecl) { AVB_TRACE_ENTRY(AVB_TRACE_ENDPOINT); openavbRC rc = OPENAVB_FAILURE; clientStream_t *ps = (clientStream_t*)pv; AVB_LOGF_INFO("SRP talker callback uid=%d: lsnrDecl=%x", ps->streamID.uniqueID, lsnrDecl); if (lsnrDecl == openavbSrp_LDSt_Ready || lsnrDecl == openavbSrp_LDSt_Ready_Failed) { // Somebody is listening - get ready to stream if (ps->fwmark != INVALID_FWMARK) { AVB_LOG_DEBUG("attach callback: already setup queues"); rc = OPENAVB_SUCCESS; } else { AVB_LOG_DEBUG("Attach callback: setting up queues for streaming"); rc = openavbSrpGetClassParams(ps->srClass, &ps->priority, &ps->vlanID, &ps->classRate); if (IS_OPENAVB_SUCCESS(rc)) { ps->fwmark = openavbQmgrAddStream(ps->srClass, ps->classRate, ps->tSpec.maxIntervalFrames, ps->tSpec.maxFrameSize); if (ps->fwmark == INVALID_FWMARK) { AVB_LOG_ERROR("Error in attach callback: unable to setup stream queues"); rc = OPENAVB_FAILURE; } else { rc = OPENAVB_SUCCESS; } } else { AVB_LOG_ERROR("Error in attach callback: unable to get class params"); rc = OPENAVB_FAILURE; } } } else { // Nobody listening if (ps->fwmark != INVALID_FWMARK) { AVB_LOG_DEBUG("Attach callback: tearing down queues"); openavbQmgrRemoveStream(ps->fwmark); ps->fwmark = INVALID_FWMARK; } rc = OPENAVB_SUCCESS; } if (IS_OPENAVB_SUCCESS(rc)) { openavbEptSrvrNotifyTlkrOfSrpCb(ps->clientHandle, &ps->streamID, x_cfg.ifname, ps->destAddr, lsnrDecl, ps->srClass, ps->classRate, ps->vlanID, ps->priority, ps->fwmark); rc = OPENAVB_SUCCESS; } AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT); return rc; }