I was looking through RFC 3550 and ran across this line and was not sure what it meant:
All header data is aligned to its natural length, i.e., 16-bit fields are aligned on even offsets, 32-bit
fields are aligned at offsets divisible by four, etc. Octets designated as padding have the value zero.
I tried looking around to figure out using keyword searches but haven't had any luck. Any help is appreciated.
Fields that are 16 bit long (2 bytes) will start at offsets divisible by 2 bytes (byte 0, 2, 4, etc). Fields that are 32 bits will start at byte 0, 4, 8, etc.
The offset is relative to the start of the header (and of the packet).
For example, if you have a header with a 16 bit (2 byte) field A and a 32 bit (4 byte) field B it will have to be arranged as follows:
A : 2 bytes
padding(zero) : 2 bytes
B : 4 bytes
Here A starts at offset 0 and B starts at offset 4.
Related
I have the following number
0000C1FF61A40000
The offset or start is 36 or 0x23
The length of the number is 12 or 0xc
Can someone help me understand how to get the resulting value? I thought the offset meant what pair of hex numbers to start with and then length would be how many to grab. There definitely aren't 36 pairs, only 8. Not sure how I'd do a length of 12 with only 8.
Each hex digit represents four binary bits. Therefore your offset of 36 bits (which BTW is 0x24, not 0x23) is equivalent to 9 hex digits. So discard the rightmost 9 digits from your original number, leaving you with 0000C1F.
Then the length of the number you want is 12 bits, which is 3 hex digits. So discard all but the rightmost 3 digits, leaving you with C1F as the answer.
If the numbers of bits had not been nice multiples of 4 then you would have had to convert the original hex number into binary, then discard offset number of bits from the right, retain only the rightmost length bits from the result, and finally convert those length bits back into hex.
Why would they chose to use a 24-bit or 40-bit (that's really odd) bit group/word size for base 64 and base 32 respectively.
Specifically, can someone explain why the the least common multiple is significant?
lcm(log2(64), 8) = 24
lcm(log2(32), 8) = 40
Base 64 encoding basically involves taking a stream of 8-bit bytes and transforming it to a stream of 6-bit characters that can be represented by printable ASCII characters.
Taking a single byte at a time means you have one 6 bit character with 2 bits left over.
Taking two bytes (16 bits) means you have two 6-bit characters with 4 bits left over.
Taking 3 bytes (24 bits) means you have three bytes that can be split exactly into 4 characters with no bits left over.
So the lcm of bytes size and character size is naturally the size you need to split your input into.
6 bit characters are chosen because this is the largest size that you can use printable ascii characters for all values. If you went up to 7 bits you would need non-printing characters.
The argument for base 32 is similar, but now you are using 5-bit characters, so the lcm of 8 and 5 is the word size. This character size allows for case insensitive printable characters, 6 bit characters require differentiating between upper and lower cases.
I'm programming my Arduino micro controller and I found some code for accepting accelerometer sensor data for later use. I can understand all but the following code. I'd like to have some intuition as to what is happening but after all my searching and reading I can't wrap my head around what is going on and truly understand.
I have taken a class in C++ and we did very little with bitwise operations or bit shifting or whatever you'd like to call it. Let me try to explain what I think I understand and you can correct me where it is needed.
So:
I think we are storing a value in x, pretty sure in fact.
It appears that the data in array "buff", slot number 1, is being set to the datatype of integer.
The value in slot 1 is being bit shifted 8 places to the left.(does this point to buff slot 0?)
This new value is being compared to the data in buff slot 0 and if either bits are true then the bit in the data stored in x will also be true so, 0 and 1 = 1, 0 and 0 = 0 and 1 and 0 = 1 in the end stored value.
The code does this for all three axis: x, y, z but I'm not sure why...I need help. I want full understanding before I progress.
//each axis reading comes in 10 bit resolution, ie 2 bytes.
// Least Significant Byte first!!
//thus we are converting both bytes in to one int
x = (((int)buff[1]) << 8) | buff[0];
y = (((int)buff[3]) << 8) | buff[2];
z = (((int)buff[5]) << 8) | buff[4];
This code is being used to convert the raw accelerometer data (in an array of 6 bytes) into three 10-bit integer values. As the comment says, the data is LSB first. That is:
buff[0] // least significant 8 bits of x data
buff[1] // most significant 2 bits of x data
buff[2] // least significant 8 bits of y data
buff[3] // most significant 2 bits of y data
buff[4] // least significant 8 bits of z data
buff[5] // most significant 2 bits of z data
It's using bitwise operators two put the two parts together into a single variable. The (int) typecasts are unnecessary and (IMHO) confusing. This simplified expression:
x = (buff[1] << 8) | buff[0];
Takes the data in buff[1], and shifts it left 8 bits, and then puts the 8 bits from buff[0] in the space so created. Let's label the 10 bits a through j for example's sake:
buff[0] = cdefghij
buff[1] = 000000ab
Then:
buff[1] << 8 = ab00000000
And:
buff[1] << 8 | buff[0] = abcdefghij
The value in slot 1 is being bit shifted 8 places to the left.(does this point to buff slot 0?)
Nah. Bitwise operators ain't pointer arithmetic, don't confuse the two. Shifting by N places to the left is (roughly) equivalent with multiplying by 2 to the Nth power (except some corner cases in C, but let's not talk about those yet).
This new value is being compared to the data in buff slot 0 and if either bits are true then the bit in the data stored in x will also be true
No. | is not the logical OR operator (that would be ||) but the bitwise OR one. All the code does is combining the two bytes in buff[0] and buff[1] into a single 2-byte integer, where buff[1] denotes the MSB of the number.
The device result is in 6 bytes and the bytes need to be rearranged into 3 integers (having values that can only take up 10 bits at most).
So the first two bytes look like this:
00: xxxx xxxx <- binary value
01: ???? ??xx
The ??? part isn't part of the result because the xxx part comprise the 10 bits. I guess the hardware is built in such a way that the ??? part is all zero bits.
To get this into a single integer variable, we need all 8 of the low bits plus the upper-order 2 bits, shifted left by 8 position so they don't interfere with the low order 8 bits. The logical OR (| - vertical bar) will join those two parts into a single integer that looks like this:
x: ???? ??xx xxxx xxxx <- binary value of a single 16 bit integer
Actually it doesn't matter how big the 'int' is (in bits) as the remaining bits (beyond that 16) will be zero in this case.
to expand and clarify the reply by Carl Norum.
The (int) typecast is required because the source is a byte. The bitshift is performed on the source datatype before the result is saved into X. Therefore it must be cast to at least 16 bits (an int) in order to bitshift 8 bits and retain all the data before the OR operation is executed and the result saved.
What the code is not telling you is if this should be an unsigned int or if there is a sign in the bit data. I'd expect -ve data is possible with an Accelerometer.
I'm given a 2 byte sequence and asked to Base64 encode it:
00000001 00010001
From what I understand you can only encode sequences of 6 bits when working with Base64.
So because 16 bits is not divisible by 6 I'm a little stuck.
The solution I can see is to convert the given 2 byte sequence into a 3 byte sequence so it becomes divisible by 6. But how do I do this without changing the value of the initial sequence?
Basically, you pad it out with zeroes to the next multiple of 6 bits, and pad out the last four-character sequence with =s. Since the last two zero bytes don't make up a full input byte, the decoder knows to ignore them. (The = padding isn't totally necessary, but it's customary to make the end result always a multiple of 4 characters long.)
For instance, the sequence you've got is:
00000001 00010001
Breaking that up into groups of 6, we get:
000000 010001 0001
Pad with zeroes:
000000 010001 000100
Convert to ASCII:
ARE
And pad that out:
ARE=
I want to calculate IP-header length with following statement:
Header Length is a four-bit field that tells, as the name implies, the
length of the IP header in 32-bit words
Now I'm getting difficulties in calculating IP header length (minimum and maximum), with four-bit field.
The minimum length of an IPv4 header of a valid datagram is 20 bytes, when the value reads 5 and there are no options
Since the field is 4 bits wide, the maximum value it can store is 15, thus the maximum length of the header is 60 bytes.
Internet Header Length is the length of the internet header in 32
bit words, and thus points to the beginning of the data. Note that
the minimum value for a correct header is 5.
Which means whatever value is stored in the IHL, it should be multiplied with 32 to get the total number of bits, or with 4 to get the total number of bytes.
minimum value of header length is 20 Bytes but we don't have sufficient bits to represent 20 so we use scaling technique, i.e. 0101 (5) will represent 4 X 5 = 20 Bytes, here scaling factor is 4.
maximum value possible with 4 bits is 15.
So maximum header length possible is 4 X 15 = 60 Bytes.
Header Length | Header Length Field
20 -----> 5
24 -----> 6
28 -----> 7
.
.
.
60 -----> 15
if header length is 22 Bytes then we use padding to make it a multiple of 4 i.e. 24 Bytes
#Amit>Value in the HL filed is = the number of 4 bytes in the total IP header length.Means if the header length field is say 40,then calculate how many 4 bytes in 40?its 40/4= 10.So value in the HL field is 10
MINIMUM HL value
Minimum HL is 20 byte .ie no of 4bytes in 20 = 20/4=5.So minimum value in HL field is 5.
MAXIMUM HL value
HL is a 4 bit field.so the maximum vale that can be accomadated in that field is 15(1111) or you can calculate using the formulae 2^4-1=15.So max no: of 4 bytes can be 15.Hence the Max header length=15*4=60bytes.
Hope now things are clear.
The Internet Header Length (IHL) field is the number of 32-bit words(=4 bytes)
in the IPv4 header, including any options. Because this is also a
4-bit field, the IPv4 header is limited to a maximum of fifteen 32-bit
words(=60 bytes)
So if the value of IHL is 0101(5), then the IP-header's length is 5*4(bytes) = 20(bytes)