What does the current(0,4) mean in parser.p4? - p4-lang

I'm studying on the p4 program code recently.
However, I do not understand what does this 'current(0,4)' mean in the parser.p4.
parser parse_mpls_bos {
extract(mpls_bos);
return select(current(0, 4)) {
0x4 : parse_ipv4;
default : ingress;
}
}
The header for mpls_bos
header_type mpls_t {
fields {
label : 20;
tc : 3;
bos : 1;
ttl : 8;
}
}
Which fields should be equals to 0x4 here to parse_ipv4?
Can someone help to explain/answer?
Thanks in advance.

current allows you to reference bits that have not been parsed yet without extract them. It is a valid statement in p4_14 but is not available in p4_16.
The first argument of current is the bit offset, 0 in this case means that you're pointing at the end of the mpls_bos header. The second argument is the width in bits.
Since MPLS layer does not contain information regarding what the next header is, here the code is working on the assumption that if the 4 bits following the MPLS header are equal to 4 then it means you are parsing the version field of the IPv4 header.
In the parse_ipv4 state you can extract the IP header without issues since the first 4-bits of its header have been used for the transition but not yet extracted.

Related

How to get the location in the compressed data - zlib

When I save the 'state of uncompression', I also need to save:
"location in the compressed data, which is both a byte offset and bit offset within that byte".
After a reboot, along with inflateSetDictionary(), I call inflatePrime() as below, "to feed the bits from the byte at the compressed data offset".
inflatePrime ( , streamBits, streamCurrentPos)
Both APIs return Z_OK, but params to inflatePrime(), I am bit uncertain.
This is how I gathered them:
typedef struct state_of_uncompression
{
uInt streamCurrentPos; // Missing this, tried the output from unzGetCurrentFileZStreamPos64()
int streamBits; // from : stream.data_type, after clearing bits 8,7,6: stream.data_type & (~0x1C0)
Byte dictionary_buf[32768]; // from : inflateGetDictionary()
uInt dictLength; // from : inflateGetDictionary();
uint64_t output_wrt_offset // got this already.
} uncompression_state_info;
So after the reboot, the plan is to recontinue the uncompression, but inflate() returns Z_STREAM_END inside unzReadCurrentFile(), as if, inflate() doesn't know where to restart from.
Thanks appreciate any feedback.
The third argument to inflatePrime() is not a position. It is the actual bits to insert, which you need to get from the compressed data. You use fseek() or lseek() to go to the byte offset in the file, where you saved that offset as part of your entry point information. You get that byte, which advances the file pointer to the next byte, and shift down by the number of bits you are not providing, i.e. 8 minus the second argument. That's the third argument. The second argument is always in 1..7. If there are no bits to insert, then you don't call inflatePrime(), and just leave the file pointer where it is to begin inflating.
The position in your state should be a 64-bit value, not a 32-bit value as you currently have it.

how to trim unknown first characters of string in code vision

I set a mega16 (16bit AVR microcontroller) to receive data from the serial port
which is connected to Bluetooth module HC-05 for attaining an acceptable number
sent by my android app and an android application sends a number in the form of a
string array whose maximum length is equal to 10 digits. The problem arrives
while receiving data such that one or two unknown characters(?) exist at the
beginning of the received string. I have to remove these unknown characters from
the beginning of the string in the case of existence.
this problem is just for HC-05. I mean I had no problem while sending numbers by
another microcontroller instead of android applications.
here is what I send by mobile:
"430102030405060\r"
and what is received in the serial port of microcontroller:
"??430102030405060\r"
or
"?430102030405060\r"
here is USART Receiver interrupt code:
//-------------------------------------------------------------------------
// USART Receiver interrupt service routine
interrupt [USART_RXC] void usart_rx_isr(void)
{
char status,data;
status=UCSRA;
data=UDR;
if (data==0x0D)
{
puts(ss);printf("\r")
a=0;
memset(ss, '\0', sizeof(ss));
}
else
{
ss[a]=data;
a+=1;
}
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
{
rx_buffer[rx_wr_index++]=data;
if RX_BUFFER_SIZE == 256
// special case for receiver buffer size=256
if (++rx_counter == 0) rx_buffer_overflow=1;
else
if (rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;
if (++rx_counter == RX_BUFFER_SIZE)
{
rx_counter=0;
rx_buffer_overflow=1;
}
endif
}
}
//-------------------------------------------------------------------------
how can I remove extra characters (?) from the beginning of received data in codevision?
You do not need to remove them, just do not pass them to your processing.
You either may test the data character before putting it into your line buffer (ss) or after the complete line was received look for the first relevant character and only pass the string starting from this position to your processing functions.
Var 1:
BOOL isGarbage(char c){
return c<'0' || c > '9';
}
if (data==0x0D)
{
puts(ss);printf("\r")
a=0;
memset(ss, '\0', sizeof(ss));
} else {
if(!isGarbage(data))
{
ss[a]=data;
a+=1;
}
}
Var2:
if (data==0x0D)
{
const char* actualString = ss;
while(isGarbage(*actualString )){
actualString ++;
}
puts(actualString );printf("\r")
a=0;
memset(ss, '\0', sizeof(ss));
} else {
ss[a]=data;
a+=1;
}
However:
maybe you should try to solve the issue in contrast to just fix the symptoms (suppress '?' characters).
What is the exact value of the questionable characters? I suspect, that '?' is only used to represent non printable data.
Maybe your interface configuration is wrong and the sender uses software flow control on the line and the suspicious characters are XON/XOFF bytes
One additional note:
You may run into trouble if you use more complex functions or even peripheral devices from your interrupt service routine (ISR).
I would strongly suggest to only fill buffers there and do all other stuff in the main loop. triggered by some volatile flags data buffers.
Also I do not get why you are using an additional buffer (ss) in the ISR, since it seems that there already is a RX-Buffer. The implementation looks like that there is a good RX-receive buffer implementation that should have some functions/possibilities to get the buffer contents within the main loop, so that you do not need to add your own code to the ISR.
Additional additional notes:
string array whose maximum length is equal to 10 digits.
I count more than that, I hope your ss array is larger than that and you also should consider the fact that something may go wrong on transmission and you get a lot more characters before the next '\n'. Currently you overwrite all your ram.

Passing params from alsa application to kernel driver

I try to follow the path of parameters setting from linux user space (arecord/aplay) down to kernel driver. Let's take arecords --period-size as an example.
It all starts in set_params function in aplay.c:
if (period_time > 0)
err = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, 0);
else
err = snd_pcm_hw_params_set_period_size_near(handle, params, &period_frames, 0);
The function snd_pcm_hw_params_set_period_size_near() is defined in [pcm.c : 5186](alsa-lib https://github.com/alsa-project/alsa-lib/blob/master/src/pcm/pcm.c#L5186), and here my headache starts... This function starts a chain of calls to other functions which doesn't make much sense to me and doesn't seem to be leading to any end call of driver.
There is _end label so I skipped all calls like snd_pcm_hw_param_set_min() or snd_pcm_hw_param_set_max() and went to snd_pcm_hw_param_set_last() hoping for some driver invocation like:
drv->hw_params_set(...);
but instead I found an end call to:
MASK_INLINE unsigned int snd_mask_min(const snd_mask_t *mask)
{
int i;
assert(!snd_mask_empty(mask));
for (i = 0; i < MASK_SIZE; i++) {
if (mask->bits[i])
return ffs(mask->bits[i]) - 1 + (i << 5);
}
return 0;
}
where return values shall be the parameter set.
So to summarize, I found alsa-lib to be very difficult to read and understand. Maybe I am lacking some knowledge though. My question is simple, how is user space parameter passed to kernel driver. Can you provide a software path showing interfaces called?
Thanks.
The hw_params structure contains a configuration space, which is a description of all possible configurations that the device can support. Numeric parameters are described as intervals (i.e., min and max), access and format as bitmasks.
When you change one parameter, the library calls the kernel driver (SNDRV_PCM_IOCTL_HW_REFINE) to adjust all the other parameters in the hw_params structure that depend on the changed parameter.
After you have reduced the configuration space to the configuration you actually want, you call snd_pcm_hw_params() (→ SNDRV_PCM_IOCTL_HW_PARAMS) to actually configure the device for those parameters. (If some parameter has not been reduced to a single value, snd_pcm_hw_params() will choose a random one.)
snd_pcm_hw_params_set_xxx_near() is more complex because there is no SET_NEAR ioctl. This function tries to adjust the interval so that either its maximum or its minimum is the desired value, and then check whether the actual maximum or minimum is nearer.
For example, assume a device that supports period sizes of 1024, 2048, 4096, and 8192 frames. Initially, the interval is described as [1024, 8192]. When you call snd_pcm_hw_params_set_period_size_near(4000), the snd_pcm_hw_param_set_near() helper function calls set_min(4000) and set_max(4000) (on separate copies of the hw_params structure), so the intervals are [1024, 4000] and [4000, 8192]; after refining, the driver returns the intervals [1024, 2048] and [4096, 8192]. snd_pcm_hw_param_set_near() then sees that 4096 is nearest to the desired calue, so it then calls set_first on the second interval, which results in [4096, 4096].

How do I publish multiple pieces of BLE characteristic data using bleno

I'm trying to learn how to implement a BLE peripheral device using bleno. I would like to discover and read from the peripheral using noble. For example sake, I want to know how I would implement a simple smart scale that reports back weight, BMI etc following the Weight Measurement GATT spec.
What I can't figure out is if reading multiple pieces of information from a characteristic is possible. The Weight Measurement GATT spec makes it seem like in a single noble characteristic.read() you can simultaneously retrieve Weight, BMI, Height etc.
For example, this simple bleno characteristic:
'use strict';
const bleno = require('bleno');
const flags = {
IMPERIAL_WEIGHT: 1 << 0,
USER_ID_PRESENT: 1 << 2,
BMI_AND_HEIGHT_PRESENT: 1 << 3
};
module.exports.flags = flags;
module.exports.WeightMeasureCharacteristic = class WeightMeasureCharacteristic extends bleno.Characteristic {
constructor(scale) {
super({
uuid: '2A9D',
properties: ['read'],
descriptors: []
});
this._scale = scale;
}
onReadRequest(offset, callback) {
//Not sure what `offset` means here or how it gets populated...Help!
let data = new Buffer.alloc(8); //1(flags)+2(weightImp)+1(userId)+2(BMI)+2(heightImp)
//Write supported value fields as bit flags
data.writeUInt8(flags.IMPERIAL_WEIGHT | flags.USER_ID_PRESENT | flags.BMI_AND_HEIGHT_PRESENT), 0);
//Write out weight (lbs) - offset 1 byte
data.writeUInt16LE(100.01, 1);
//Write out user id - offset 12 bytes (flags+Imperial, no need to include offset for SI or Timestamp since the flags indicated those are not supported)
data.writeUInt8(69, 3);
//Write out BMI - offset 13 bytes (after UserId)
data.writeUInt16LE(18.6, 4);
//Write out Height Imperial - offset 17 bytes (after Height SI)
data.writeUInt16LE(72.2, 6);
callback(this.RESULT_SUCCESS, data);
}
}
If someone was able to implement/pseudocode onReadRequest() above I think it would help things click in my head.
Questions:
Does the C<number> value in the "Field Requirement" column of the spec indicate the offset value passed into onReadRequest()? If a consumer wanted to get "Weight - SI"(C1) they would somehow construct a noble characteristic.read() that triggers an onReadRequest(1,function())? If so, how is the characteristic.read() constructed?
How do I construct a noble characteristic.read() to get the value of the Flags?
How do I construct a noble characteristic.read() that will return me multiple (or all) properties in one read? Ex: Give me all values this peripheral supports (Weight - SI, BMI etc).
If my peripheral supports imperial weight, user id, bmi, and height how do I populate the data for the callback in onReadRequest(). Is what I have above correct?
How is offset populated & what does it mean in onReadRequest(offset,callback)?
Or, am I doing this all wrong? Should I have a characteristic for each value? Ex: a single characteristic for weight - SI, and another characteristic for BMI? I would like to avoid this, would prefer to save round trips and get multiple values in one call.
An attempt to answer your question:
I am not sure what the C<number> means, but I believe that each field (Weight, BMI, Height, etc.) is represented as a group of one or more octets. Notice how at the bottom of the spec it says
Note: The fields in the above table are in the order of LSO to MSO.
Where LSO = Least Significant Octet and MSO = Most Significant Octet.
Thus, I believe that in order to get the "Weight - SI" field, you would do something like:
characteristic.read((err, data) => {
let char_flags = data.readUint8(0); // read first bit
if (!(char_flags & flags.IMPERIAL_WEIGHT)) // if SI weight
let weightSI = data.readUint16LE(1) // read SI weight starting at second bit
});
Answered above
Answered above, just check whether the property exists in the flags and then read the value from the appropriate offset. Also this might help.
Answered above.

skb->priority and IP::tos and ping -Q

I'm developing some network driver and I'm trying to assign packets to different queues basing on ip::tos value. For testing purposes I'm running:
ping -Q 1 10.0.0.2
to set ip::tos value to 1. The problem I've got is that on this system where I run ping command - outgoing skb has skb->priority==0, but I think it should be 1.
I assumed that setting "-Q 1" will set skb->priority to 1, but it isn't.
Anyone knows why?
First of all, there is no direct mapping between the skb->priority and the IP TOS field. It is done like so in the linux kernel:
sk->sk_priority = rt_tos2priority(val)
...
static inline char rt_tos2priority(u8 tos)
{
return ip_tos2prio[IPTOS_TOS(tos)>>1];
}
(and the ip_tos2prio table can be found in ipv4/route.c).
It seems to me you'll have to set the "TOS" byte to atleast 32 to get skb->priority to anything other than 0.
ping -Q 1 sets the whole TOS byte to 1. Note that TOS is deprecated in favor of DSCP. The 2 low-order bits are used for ECN, while the upper 6 bits are used for the DSCP value (the "priority").
So you likely have to start at 4, to get a DSCP priority of 1, but according to the above table, start at 32 to get skb->priority set as well, as in ping -Q 32 10.0.0.2
However, I'm not sure that will set the skb->priority as well in all cases. If the ping tool crafts packets using raw sockets, it might bypass setting the skb->priority.
However, skb->priority for locally generated packets will be set if one does e.g.
int tos = 32;
setsockopt(sock_fd, IPPROTO_IP, IP_TOS,
&tos, sizeof(tos));
So you might need to cook up a small sample program that does the above before sending packets.
The above answer is right, Let's complete it here
static inline char rt_tos2priority(u8 tos)
{
return ip_tos2prio[IPTOS_TOS(tos)>>1];
}
where IPTOS_TOS is a macro, which ANDs "tos" value with 0x1E
So, If you give TOS as 0xFF, the above return statement reduces to
return ip_tos2prio[(0x1E & 0xFF)>>1];
calculate it further, (0x1E & 0xFF) is equal to 0x1E,
and (0x1E >> 1) gives us 0x0F, which is 15 in decimal.
we can say that above return statement is equal to
return ip_tos2prio[15];
Now "ip_tos2prio" is a predefined array, like this
const __u8 ip_tos2prio[16]={0,0,0,0,2,2,2,2,6,6,6,4,4,4,4};
where each distinct value has a meaning, 0->BESTEFFORT, 2->BULK, 4->INTERACTIVE BULK, 6 ->INTERACTIVE.
get back to the return statement, it returns the 15th element in ip_tos2prio array, which is 4.

Resources