📄 mapping.c
字号:
/*
* LICENSE NOTICE.
*
* Use of the Microsoft Windows Rally Development Kit is covered under
* the Microsoft Windows Rally Development Kit License Agreement,
* which is provided within the Microsoft Windows Rally Development
* Kit or at http://www.microsoft.com/whdc/rally/rallykit.mspx. If you
* want a license from Microsoft to use the software in the Microsoft
* Windows Rally Development Kit, you must (1) complete the designated
* "licensee" information in the Windows Rally Development Kit License
* Agreement, and (2) sign and return the Agreement AS IS to Microsoft
* at the address provided in the Agreement.
*/
/*
* Copyright (c) Microsoft Corporation 2005. All rights reserved.
* This software is provided with NO WARRANTY.
*/
/* This is the state machine that controls the topology mapping process, smT.
* Once enumeration by a Topology-Discovery Mapper has been completed, that
* mapper alone is enabled to make other requests of the Responder, until it
* relinquishes its lock on the Responder, either by sending a Reset or by
* timing out (Inactivity timeout).
*
* A session conceptually represents the association of a Mapper with this
* Responder, throughout the lifetime of that association. State-information
* for smT is maintained in one area of the process globals, since there is
* at most one session associated with the Responder process at a time.
*
**/
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "globals.h"
#include "statemachines.h"
#include "packetio.h"
static
int
SufficientChargeAvailable()
{
IF_DEBUG
dbgprintf("SCA: ctc_pkts=" FMT_UINT32 " pkts_needed=" FMT_UINT32 \
" ctc_bytes=" FMT_UINT32 " bytes_needed=" FMT_UINT32 "\n",
g_ctc_packets, g_neededPackets, g_ctc_bytes, g_neededBytes);
END_DEBUG
if ((g_ctc_packets >= g_neededPackets) && (g_ctc_bytes >= g_neededBytes))
return TRUE;
else
return FALSE;
}
static void
ProcessEmits()
{
topo_ether_header_t *ehdr; /* pointer to ethernet header in emit buf */
topo_base_header_t *bhdr; /* pointer to base header in emit buf */
topo_emit_header_t *emit; /* pointer to emit header in emit buf */
/* copy current rxbuf into the emit buffer */
memcpy(g_emitbuf, g_rxbuf, g_rcvd_pkt_len);
/* setup the emit machinery */
assert(g_emit_remaining == 0);
g_emit_remaining = g_this_event.numDescrs;
g_emit_seqnum = g_sequencenum; /* might be zero for an unreliable Emit */
ehdr = (topo_ether_header_t*)(g_emitbuf);
bhdr = (topo_base_header_t*)(ehdr + 1);
emit = (topo_emit_header_t*)(bhdr + 1);
g_emitdesc = (topo_emitee_desc_t*)(emit + 1); // pointer to the first descriptor
}
static
void
ChargeAdd(int pktlen)
{
struct timeval now;
g_ctc_packets++;
if (g_ctc_packets > TOPO_CTC_PACKETS_MAX)
g_ctc_packets = TOPO_CTC_PACKETS_MAX;
g_ctc_bytes += pktlen;
if (g_ctc_bytes > TOPO_CTC_BYTES_MAX)
g_ctc_bytes = TOPO_CTC_BYTES_MAX;
IF_TRACED(TRC_CHARGE)
dbgprintf("ChargeAdd: CTC now has bytes=" FMT_UINT32 " & packets=" FMT_UINT32 "\n",
g_ctc_bytes, g_ctc_packets);
END_TRACE
/* Reset charge timer */
gettimeofday(&now, NULL);
timeval_add_ms(&now, TOPO_CHARGE_TIMEOUT);
CANCEL(g_charge_timer);
g_charge_timer = event_add(&now, state_charge_timeout, /*state:*/NULL);
}
static
void
ChargeConsume(int pktlen)
{
struct timeval now;
if (g_ctc_packets)
g_ctc_packets--;
if (g_ctc_bytes)
g_ctc_bytes -= pktlen;
IF_TRACED(TRC_CHARGE)
dbgprintf("ChargeConsume: CTC now has bytes=" FMT_UINT32 " & packets=" FMT_UINT32 "\n",
g_ctc_bytes, g_ctc_packets);
END_TRACE
/* Reset charge timer */
gettimeofday(&now, NULL);
timeval_add_ms(&now, TOPO_CHARGE_TIMEOUT);
CANCEL(g_charge_timer);
g_charge_timer = event_add(&now, state_charge_timeout, /*state:*/NULL);
}
/*********************** Q U I E S C E N T S T A T E ***********************/
static
enum sm_Status
smT_QuiescentHandler( protocol_event_t* evt )
{
IF_TRACED(TRC_STATE)
if (evt->evtType != evtBlockTimeout)
{
printf("smT (Quiescent): Entered with event %s",smEvent_names[evt->evtType]);
if (g_this_event.evtType==evtPacketRcvd)
{
printf(" (%s)\n",Topo_opcode_names[g_opcode]);
} else {
puts("");
}
}
END_TRACE
switch (evt->evtType)
{
case evtPacketRcvd:
switch (g_opcode)
{
case Opcode_Charge:
case Opcode_Probe:
case Opcode_Query:
case Opcode_QueryLargeTlv:
IF_TRACED(TRC_PACKET)
printf("smT (Quiescent): Hoisting packet ignored.\n");
END_TRACE
break;
case Opcode_Emit: // should never occur - explicit event
case Opcode_Reset: // should never occur - explicit event
case Opcode_Discover: // should never occur - explicit event
case Opcode_Hello:
case Opcode_Train:
case Opcode_ACK:
case Opcode_QueryResp:
case Opcode_Flat:
case Opcode_QueryLargeTlvResp:
IF_TRACED(TRC_STATE)
printf("smT (Quiescent): Ignored packet w/ known opcode: %s\n",
Topo_opcode_names[g_opcode]);
END_TRACE
break;
default:
warn("smT (Quiescent): Ignored packet w/ unknown opcode: %d\n",g_opcode);
return PROCESSING_ABORTED;
} /*** end of switch (g_opcode) ***/
break;
case evtDiscoverRcvd:
if (evt->isAckingMe)
{
uint16_t gen = ntohs(g_discover_hdr->mh_gen);
if (evt->isInternalEvt == FALSE && // if a real acking-Discover,
gen != 0 && // has a non-zero gen,
g_generation != gen) // that differs from ours,
{ g_generation = gen; } // then save it for future Hellos.
IF_TRACED(TRC_STATE)
printf("smT (Quiescent): Leaving for Command state\n");
END_TRACE
g_smT_state = smT_Command;
}
break;
case evtInactivityTimeout:
case evtResetRcvd:
/* If the Topo-session was reset, */
if (evt->ssn == g_topo_session)
{
/* zero the credits, and clear the charge-timer */
g_ctc_packets = g_ctc_bytes = 0;
CANCEL(g_charge_timer);
/* and NULL the g_topo_session ptr */
g_topo_session = NULL;
}
break;
case evtEmitRcvd:
IF_TRACED(TRC_PACKET)
printf("smT (Quiescent): Hoisting packet (Emit) ignored.\n");
END_TRACE
break;
case evtBlockTimeout:
break;
case evtChargeTimeout:
case evtEmitTimeout:
case evtHelloDelayTimeout:
default:
IF_DEBUG
printf("smT (Quiescent): Ignored event %s\n",smEvent_names[evt->evtType]);
END_DEBUG
break;
} /*** end of switch (eventType) ***/
return PROCESSING_COMPLETED;
}
/*********************** C O M M A N D S T A T E ***********************/
static
enum sm_Status
smT_CommandHandler( protocol_event_t* evt )
{
IF_TRACED(TRC_STATE)
if (evt->evtType != evtBlockTimeout)
{
printf("smT (Command): Entered with event %s",smEvent_names[evt->evtType]);
if (g_this_event.evtType==evtPacketRcvd)
{
printf(" (%s)\n",Topo_opcode_names[g_opcode]);
} else {
puts("");
}
}
END_TRACE
switch (evt->evtType)
{
case evtPacketRcvd:
switch (g_opcode)
{
case Opcode_Charge:
ChargeAdd(g_rcvd_pkt_len); // also restarts the charge-timeout timer
if (g_sequencenum)
{
packetio_tx_flat();
ChargeConsume(g_tx_len);
}
break;
case Opcode_Probe:
IF_TRACED(TRC_PACKET)
printf("smT (Command): Logging Probe from " ETHERADDR_FMT "\n",ETHERADDR_PRINT(&g_base_hdr->tbh_realsrc));
END_TRACE
seeslist_enqueue(FALSE, &g_base_hdr->tbh_realsrc);
break;
case Opcode_Query:
IF_TRACED(TRC_PACKET)
printf("smT (Command): Sending query-Resp\n");
END_TRACE
packetio_tx_queryresp();
break;
case Opcode_QueryLargeTlv:
{
tlv_desc_t *tlvDescr = Tlvs;
/* search the TLVs, which may not be consecutive or in order, for one with the given number */
for (;tlvDescr->number != 0; tlvDescr++)
{
if (tlvDescr->number == g_qltlv_hdr->qh_type)
{
size_t offset;
IF_TRACED(TRC_PACKET)
printf("smT (Command): Sending qltlv-Resp with LTLV # 0x%X\n", tlvDescr->number);
END_TRACE
offset = ntohs(g_qltlv_hdr->qh_offset) + (g_qltlv_hdr->qh_rsvd1 << 16);
packetio_tx_qltlvResp(g_sequencenum, tlvDescr, offset);
break;
}
}
/* if it falls out without finding a match, nothing will be sent */
}
break;
case Opcode_Emit: // should never occur - explicit event
case Opcode_Reset: // should never occur - explicit event
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -