a tricky expression

M

Mark

Hi

Trying to understand some application dealing with VLANs and can't figure
out what this piece of code does:

#define MAX_PORTS_IN_UNIT 28
#define MAX_VLAN_ID 4095
#define VLAN_BITMAP_ARRAY_SIZE (MAX_VLAN_ID/32+1)

unsigned long vlan_member_array[VLAN_BITMAP_ARRAY_SIZE];

int sw_is_set_vlan_bit(unsigned long *VlanBitArray, int vlan_id)
{
return (VlanBitArray[(vlan_id - 1) / 32] & (1 << ((vlan_id - 1) % 32)));
}
....
int port;
for (port = 0; port < MAX_PORTS_IN_UNIT; port++) {
....
/* Set PVID for each port */
if (!sw_is_set_vlan_bit(vlan_member_array, pvid)) {
printf("PVID Error!\n");
} else {
.....
}
....
}

Here is a loop running through the ports (let's say 24) and calling
sw_is_set_vlan_bit() for each port:

The code is huge, I hope the snippet I'm providing will suffice. So my
questions are:

1) why to define an array of (MAX_VLAN_ID/32+1) size. What does it indicate?

2) what exactly does the function do?

Thanks!
 
I

Ian Collins

Mark said:
Hi

Trying to understand some application dealing with VLANs and can't
figure out what this piece of code does:

#define MAX_PORTS_IN_UNIT 28
#define MAX_VLAN_ID 4095
#define VLAN_BITMAP_ARRAY_SIZE (MAX_VLAN_ID/32+1)

unsigned long vlan_member_array[VLAN_BITMAP_ARRAY_SIZE];

int sw_is_set_vlan_bit(unsigned long *VlanBitArray, int vlan_id)
{
return (VlanBitArray[(vlan_id - 1) / 32] & (1 << ((vlan_id - 1) % 32)));
}
Here is a loop running through the ports (let's say 24) and calling
sw_is_set_vlan_bit() for each port:

The code is huge, I hope the snippet I'm providing will suffice. So my
questions are:

1) why to define an array of (MAX_VLAN_ID/32+1) size. What does it
indicate?

It looks like an attempt to declare an array MAX_VLAN_ID and a bit long.
This will fail (or rather consume too much space) on a 64 bit ILP64
system.
2) what exactly does the function do?

It tests the appropriate bit by working out which element the vlan_id is
in (VlanBitArray[(vlan_id - 1) / 32]) and which it in the element it is
(1 << ((vlan_id - 1) % 32)).

This code is a horrible hack, assuming sizeof(unsigned long) == 32.
Where is it from?
 
N

Nick

Mark said:
Hi

Trying to understand some application dealing with VLANs and can't
figure out what this piece of code does:

#define MAX_PORTS_IN_UNIT 28
#define MAX_VLAN_ID 4095
#define VLAN_BITMAP_ARRAY_SIZE (MAX_VLAN_ID/32+1)

unsigned long vlan_member_array[VLAN_BITMAP_ARRAY_SIZE];

int sw_is_set_vlan_bit(unsigned long *VlanBitArray, int vlan_id)
{
return (VlanBitArray[(vlan_id - 1) / 32] & (1 << ((vlan_id - 1) % 32)));
}
...
int port;
for (port = 0; port < MAX_PORTS_IN_UNIT; port++) {
...
/* Set PVID for each port */
if (!sw_is_set_vlan_bit(vlan_member_array, pvid)) {
printf("PVID Error!\n");
} else {
....
}
...
}

Here is a loop running through the ports (let's say 24) and calling
sw_is_set_vlan_bit() for each port:

The code is huge, I hope the snippet I'm providing will suffice. So my
questions are:

1) why to define an array of (MAX_VLAN_ID/32+1) size. What does it
indicate?

Its assuming it's running on a machine with 32 bit integers (but in a
safe way - it will just waste space if on one with bigger ones, and they
can't be smaller), and creating an array with one bit for each port. It
divides by 32 to get the number of bits it needs, but adds one because
if you have, say, 39 bits you need 2 slots, not one. This will also
waste a 32 bit slot if MAX_VLAN_ID is divisible by 32, but again,
nothing to worry about.
2) what exactly does the function do?

It checks to see if the appropriate bit in the array I've just talked
about is set. The part left of the & finds out which slot to use (so it
divides by zero) and the part right of the & finds the bit inside the
slot.

Somewhere there must be code to set the bits, which will look very
similar.

There is a bug in the code - the comment.

If you don't understand this, don't play with it!
 
M

Mark

Ian said:
It looks like an attempt to declare an array MAX_VLAN_ID and a bit
long. This will fail (or rather consume too much space) on a 64 bit
ILP64 system.

Do you mean that they assume sizeof(unsigned long)=32 and MAX_VLAN_ID/32
will yield the _number_ of 32-bit long elements? Hm, no sense I guess or I
am misunderstanding.
unsigned long vlan_member_array[VLAN_BITMAP_ARRAY_SIZE];

int sw_is_set_vlan_bit(unsigned long *VlanBitArray, int vlan_id)
{
return (VlanBitArray[(vlan_id - 1) / 32] & (1 << ((vlan_id - 1) %
32))); }
It tests the appropriate bit by working out which element the vlan_id
is in (VlanBitArray[(vlan_id - 1) / 32]) and which it in the element
it is (1 << ((vlan_id - 1) % 32)).

Alright, a bit warmer. But why to do division and modulo operation, what
does it give?
This code is a horrible hack, assuming sizeof(unsigned long) == 32.
Where is it from?
It is from our code base that I have to maintain. Alas, no documentation.
 
N

Nick

Mark said:
Ian said:
It looks like an attempt to declare an array MAX_VLAN_ID and a bit
long. This will fail (or rather consume too much space) on a 64 bit
ILP64 system.

Do you mean that they assume sizeof(unsigned long)=32 and
MAX_VLAN_ID/32 will yield the _number_ of 32-bit long elements? Hm, no
sense I guess or I am misunderstanding.
unsigned long vlan_member_array[VLAN_BITMAP_ARRAY_SIZE];

int sw_is_set_vlan_bit(unsigned long *VlanBitArray, int vlan_id)
{
return (VlanBitArray[(vlan_id - 1) / 32] & (1 << ((vlan_id - 1) %
32))); }
It tests the appropriate bit by working out which element the vlan_id
is in (VlanBitArray[(vlan_id - 1) / 32]) and which it in the element
it is (1 << ((vlan_id - 1) % 32)).

Alright, a bit warmer. But why to do division and modulo operation,
what does it give?

It does what I said when you snipped it. Think about it. Take a couple
of numbers and work it out on paper. Then go off and read about bit
manipulation - this is a pretty standard idiom.
It is from our code base that I have to maintain. Alas, no documentation.

Ah.
 
I

Ian Collins

Mark said:
Do you mean that they assume sizeof(unsigned long)=32 and MAX_VLAN_ID/32
will yield the _number_ of 32-bit long elements? Hm, no sense I guess or
I am misunderstanding.

They intend the array to be MAX_VLAN_ID *bits* long, assuming
sizeof(unsigned long) == 32.
unsigned long vlan_member_array[VLAN_BITMAP_ARRAY_SIZE];

int sw_is_set_vlan_bit(unsigned long *VlanBitArray, int vlan_id)
{
return (VlanBitArray[(vlan_id - 1) / 32] & (1 << ((vlan_id - 1) %
32))); }
It tests the appropriate bit by working out which element the vlan_id
is in (VlanBitArray[(vlan_id - 1) / 32]) and which it in the element
it is (1 << ((vlan_id - 1) % 32)).

Alright, a bit warmer. But why to do division and modulo operation, what
does it give?

The division gives the element in the array, the modulo operator gives
the bit position, modulo 32.
It is from our code base that I have to maintain. Alas, no documentation.

Good luck!
 
B

Ben Bacarisse

Ian Collins said:
They intend the array to be MAX_VLAN_ID *bits* long, assuming
sizeof(unsigned long) == 32.

You mean it assumes sizeof(unsigned long) * CHAR_BIT == 32 (and no
padding bits in unsigned long, of course).

<snip>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,142
Latest member
arinsharma
Top