📄 zl5011xpktpassthru.c
字号:
Sint32T loop;
for (loop = startSearch; loop >= 0; loop--)
{
if (zl5011xParams->wanIf.plaCurrent.context[loop].state == ZL5011X_STATE_NOT_IN_USE)
{
/* Found an unused context */
par->context[i] = loop;
startSearch = loop-1; /* Start next context search from where we are */
break;
}
}
if (loop < 0)
{ /* No spare context could be found */
status = ZL5011X_CONTEXTID_RANGE; /* Could be a better error return */
}
/* Context number is now in par->context[i] */
}
}
}
/* Find available classification matches if they have not been specified.
The following constraints apply:
a) the classification match for packet-to-packet flow 0 must take precedence over the other
individual packet-to-packet flows.
b) the classification matches used should be low enough in priority that other higher priority
matches could be used if required by the application.
c) ideally the classification match should be high enough in priority that it can
be detected in a minimum number of clock cycles in order to maximise throughput.
The application is free to use the classifications in any way it sees fit so for the general
case finding suitable combinations of matches would be a complicated search process.
In addition, b) and c) are mutually exclusive and a compromise has to be reached
Therefore we make a gross simplification and use two fixed context numbers which meet the
above criteria. The selection is somewhat arbitrary.
Furthermore we assume that if one of the contexts is not specified then we are free to choose
both, overriding any application selection of the other. So an application must specify both
or neither.
It is possible that either of the two matches chosen automatically could already be in use.
In this case an error will be returned when they are attempted to be created. Manual override
of the classification numbers would then be necessary */
/* Check that all the classifiers are either specified or all not specified */
if (status == ZL5011X_OK)
{
for (i = 1; (status == ZL5011X_OK) && (i < ZL5011X_NUM_PKT_PKT_FLOWS); i++)
{
/* If first match number is not specified all other match numbers must also not be specified */
if ((par->classifyMatchNum[0] == (Uint32T)ZL5011X_INVALID) &&
(par->classifyMatchNum[i] != (Uint32T)ZL5011X_INVALID))
{
status = ZL5011X_PARAMETER_INVALID;
}
/* If first match number is specified all other match numbers must also be specified */
else if ((par->classifyMatchNum[0] != (Uint32T)ZL5011X_INVALID) &&
(par->classifyMatchNum[i] == (Uint32T)ZL5011X_INVALID))
{
status = ZL5011X_PARAMETER_INVALID;
}
}
}
/* Now assign the matches automatically if required */
if ((status == ZL5011X_OK) && (par->classifyMatchNum[0] == (Uint32T)ZL5011X_INVALID))
{
/* Place the lowest priority classification at the lowest context number available
This will allow the application to use the higher level contexts for normal streams
if required */
Uint32T priority = zl5011xParams->devLimits.numContexts-1;
for (i = ZL5011X_NUM_PKT_PKT_FLOWS-1; i >= 0; i--)
{
par->classifyMatchNum[i] = zl5011xGetClassifierNumFromPriorityOrder(priority);
priority--; /* Now search for the next highest priority match */
}
}
/* We have now fixed all the automatically allocated values */
/* Create the two packet-to-packet flows */
for (i = 0; (status == ZL5011X_OK) && (i < ZL5011X_NUM_PKT_PKT_FLOWS); i++)
{
{
zl5011xContextCreateS contextCreateStruct;
if (status == ZL5011X_OK)
{
status = zl5011xLanLanContextCreateStructInit(zl5011xParams, &contextCreateStruct);
}
if (status == ZL5011X_OK)
{
contextCreateStruct.flow = ZL5011X_FLOW_PKT_PKT;
contextCreateStruct.osExclusionEnable = ZL5011X_FALSE;
contextCreateStruct.context = par->context[i];
status = zl5011xLanLanContextCreate(zl5011xParams, &contextCreateStruct);
}
}
/* Create the rx packet matches */
{
zl5011xPacketRxSetHeaderS packetRxSetHeader;
Uint8T header[64] = {0};
if (status == ZL5011X_OK)
{
status = zl5011xPacketRxSetHeaderStructInit(zl5011xParams, &packetRxSetHeader);
}
/* Set up a single protocol match to match on basic Ethernet protocol.
This actually gets called once for each context but it will only
be created once as the second call should reuse the same protocol
match created for the first one */
if (status == ZL5011X_OK)
{
/* Set the passed in parameters */
packetRxSetHeader.protocolType = ZL5011X_ETHERNET;
packetRxSetHeader.header = header; /* Header content is unused for ZL5011X_ETHERNET protocol
when matchDestMacAddress is ZL5011X_FALSE */
packetRxSetHeader.headerLength = 0; /* Header length is also unused */
packetRxSetHeader.protocolMatchNumber = par->protocolMatchNum;
/* Set protocol specific parameters */
packetRxSetHeader.enableVlan = ZL5011X_FALSE;
packetRxSetHeader.enableSnap = ZL5011X_FALSE;
/* Use no predefined protocol matches or classification match options */
packetRxSetHeader.matchDestMacAddress = ZL5011X_FALSE;
packetRxSetHeader.matchDestIpv4Address = ZL5011X_FALSE;
packetRxSetHeader.enableClassificationChecks = ZL5011X_FALSE;
/* Control explicitly the following parameter values */
packetRxSetHeader.removeHeader = ZL5011X_FALSE; /* Leave header in place so the original packet is unchanged */
/* Use the raw length of the packet (including any padding) */
packetRxSetHeader.lengthUsage = ZL5011X_PACKET_LENGTH_FROM_PKT;
packetRxSetHeader.payloadLength = 0; /* Unused */
packetRxSetHeader.osExclusionEnable = ZL5011X_FALSE; /* Exclusion is done in the current function, if required */
/* Set the protocol match */
status = zl5011xPacketRxSetProtocol(zl5011xParams, &packetRxSetHeader);
}
if (status == ZL5011X_OK)
{
/* Store the protocol match used into the parameter return structure */
par->protocolMatchNum = packetRxSetHeader.protocolMatchNumber;
}
}
/* Set the context specific matches */
{
zl5011xLanRxSetContextMatchS contextMatch;
if (status == ZL5011X_OK)
{
status = zl5011xLanRxSetContextMatchStructInit(zl5011xParams, &contextMatch);
}
/* Set the context match parameters */
if (status == ZL5011X_OK)
{
/* Set the criteria to match against */
/* Only process packets which have already been matched by the protocol match above */
contextMatch.match.protocolMatchNum = par->protocolMatchNum;
contextMatch.match.classifyCheckBytes[0] = 0; /* Don't use the check bytes */
/* Set what we want to come out of the classifier */
/* Remove none of the header */
contextMatch.output.classifyHeaderOffset = 0;
/* The length of the packet should be determined from the raw packet length as it was received */
contextMatch.output.classifyLengthFromPacket = ZL5011X_TRUE;
/* Therefore the following fields relating to length calculation are not applicable since these only apply if the protocol contains
a length field. They can be left at their default settings.
contextMatch.output.classifyLengthNoCalc = ZL5011X_TRUE; Don't calculate length
contextMatch.output.classifyLengthModifier = 0; No modification to length
contextMatch.output.classifyTwoByteLength = ZL5011X_FALSE; */
contextMatch.output.classifyFlow = (zl5011xFlowTypeE)ZL5011X_INVALID; /* The flow was specifed when the context was created so don't need
to specify it again here. */
contextMatch.output.classifyMpid = (Uint32T)ZL5011X_INVALID; /* Allow internal multi purpose ID to be set automatically.
This field would only be used in exceptional cases. */
contextMatch.osExclusionEnable = ZL5011X_FALSE; /* device access is already locked if required */
contextMatch.context = par->context[i];
contextMatch.matchNum = par->classifyMatchNum[i];
if (i==0)
{
Uint8T internalPortNum;
/* We will obtain the mac address of the up link from the low level API and therefore
we need to map the external port number (0 or 1) to the internal port number (1 or 3) */
status = zl5011xPkiExternalPortToInternal(zl5011xParams, &internalPortNum, par->upLinkPort);
if (status == ZL5011X_OK)
{
/* Default setting for the classify match/mask bytes is for all bytes to be masked out
For the first classification we are interested in any destination MAC address and
the source MAC address the same as the uplink MAC address. So set the match
bytes and mask bytes accordingly.
The ZL5011X_ETHERNET protocol template extracts the first 12 bytes of the
packet to be used in the classification and therefore the source MAC address is
bytes 6-11 in the classification byte array, i.e. starting at position
ZL5011X_MAC_SIZE */
memcpy(&contextMatch.match.classifyMatchBytes[ZL5011X_MAC_SIZE],
zl5011xParams->pki.lanPort[internalPortNum].macAddress, ZL5011X_MAC_SIZE);
/* Mask in these bytes */
memset(&contextMatch.match.classifyMaskBytes[ZL5011X_MAC_SIZE],ZL5011X_MASK_IN,ZL5011X_MAC_SIZE);
}
}
else
{
/* For the second classification rule we are interested in any destination MAC
and any source MAC address
So mask out all the match bytes */
memset(&contextMatch.match.classifyMaskBytes[0],ZL5011X_MASK_OUT,ZL5011X_MAC_SIZE*2);
}
if (status == ZL5011X_OK)
{
status = zl5011xLanRxSetContextMatch(zl5011xParams, &contextMatch);
}
if (status == ZL5011X_OK)
{
/* Store the classifier match used into the parameter return structure */
par->classifyMatchNum[i] = contextMatch.matchNum;
}
}
}
/* Now set up the packet transmit.
The packet is to be unchanged apart from possibly changing the source MAC address so
add a zero length header. */
{
zl5011xPacketTxSetHeaderS packetTxSetHeader;
if (status == ZL5011X_OK)
{
status = zl5011xPacketTxSetHeaderStructInit(zl5011xParams, &packetTxSetHeader);
}
if (status == ZL5011X_OK)
{
/* Set the parameters supplied by the application */
packetTxSetHeader.header = NULL; /* Add no header */
packetTxSetHeader.headerLength = 0;
packetTxSetHeader.ethernetSrcAddressFromMac = ZL5011X_FALSE; /* Don't overwrite Ethernet Src Add */
packetTxSetHeader.osExclusionEnable = ZL5011X_FALSE;
/* Set the context match parameters that are unique for each required match */
packetTxSetHeader.context = par->context[i];
if (i==0)
{ /* First flow transmits on uplink port */
packetTxSetHeader.portNum = par->upLinkPort;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -