1

i have some python code which i want to use in an 100% php code. have you any ideas how i can convert the code ??? i have problems with converting the code especially the part get bit and set bit.

The bitmask is read out from a switch via snmp and the mask represent witch ports are in a defined vlan. Example:

snmpget 1.3.6.1.2.1.17.7.1.4.3.1.2. returns an HEX String like F100000000000000

Every hex digit represents 4 physically LAN ports of the switch. The first digit in this example is F which means in binary 1111. This means that every port from 1-4 is in the vlan.

If you want only port 1,2 and 4 the mask will be 1101 and is in hex D.

The goal of the code is that i want to know for example if port 15 is in the vlan or not (getbitatposition) and if not that i can change the bitmask at the position of the port (setbitatposition).

Port 15 for example is in char 4 from left:

F = Port 1-4

1 = Port 5-8

0 = Port 9-12

0 = Port 13-16 => HEX 0 => Binary 0000

To get port 15 in the vlan i must change the 3rd bit from 0000 to 0010 and convert it back to hex => 2.

The new mask will be for example F102000000000000

The python code:

def convertHexCharacterToInt(char):
    if (char.upper() == "A"):
        return 10
    elif (char.upper() == "B"):
        return 11
    elif (char.upper() == "C"):
        return 12
    elif (char.upper() == "D"):
        return 13
    elif (char.upper() == "E"):
        return 14
    elif (char.upper() == "F"):
        return 15
    else:
        return (int(char))

def convertIntToHexCharacter(integer):
    if (integer < 0 or integer > 15):
        return "-1"

    if (integer < 10):
        return str(integer)
    elif (integer == 10):
        return "A"
    elif (integer == 11):
        return "B"
    elif (integer == 12):
        return "C"
    elif (integer == 13):
        return "D"
    elif (integer == 14):
        return "E"
    elif (integer == 15):
        return "F"   

def __getBitAtPosition(position, bitmap):

    for x in range(0, len(bitmap)):
        mask = 0x8
        for y in range(0, 4):
            if (((x * 4) + y + 1) == position):
                return (convertHexCharacterToInt(bitmap[x]) & mask) != 0
            mask = mask >> 1

    return None

def __setBitAtPosition(position, bitmap, value):

    if (__getBitAtPosition(position, bitmap) == value):
        return bitmap

    charPosition = (position + 3) / 4 - 1
    bitPosition = int(math.fabs((position - (charPosition * 4)) - 4))

    bitValue = 2 ** bitPosition
    fourBitValue = convertHexCharacterToInt(bitmap[charPosition])

    newValue = None

    if (value):
        newValue = fourBitValue + bitValue
    else:
        newValue = fourBitValue - bitValue
    newBitmap = bitmap[:charPosition] + convertIntToHexCharacter(newValue) + bitmap[charPosition + 1:]
    return newBitmap

This was my first try but the result is not the same:

private function _convertHexCharacterToInt($char){

    if (strtoupper($char) == "A"){
        return 10;}
    elseif (strtoupper($char) == "B"){
        return 11;}
    elseif (strtoupper($char) == "C"){
        return 12;}
    elseif (strtoupper($char) == "D"){
        return 13;}
    elseif (strtoupper($char) == "E"){
        return 14;}
    elseif(strtoupper($char) == "F"){
        return 15;}
    else {
        return $char;
    }
}

private function _getBitAtPosition($pos,$bitmap){

    foreach(range(0,strlen($bitmap)) as $x){
    $mask=0x8;

    foreach(range(0,3) as $y){
      if((($x * 4) + $y + 1) == $pos){

        if($this->_convertHexCharacterToInt(substr($bitmap,$x,1))&$mask != 0{
          return $this->_convertHexCharacterToInt(substr($bitmap,$x,1))&$mask;
        }

        $mask = $mask >> 1

      }
    }

    }

}
max
  • 11
  • 2
  • At first: you reinvented the wheel. Both Python (`hex(x)`, `int(x, 16)`) and PHP (`hexdec(x)`, `dechex(x)`) have function built-in to do int - hex conversion. Also it would be helpful to have a description what you expect the other two functions to do. What is bitmap (type, example data)? – Klaus D. Feb 23 '15 at 10:03
  • You are right i have reinvented the wheel. :-) – max Feb 23 '15 at 10:34
  • I already found the solution by myself after some problems converting is not my favorite hobby ... – max Feb 23 '15 at 19:47

3 Answers3

0

I can solve the first part, i think it work:

private function _getBitAtPosition($pos,$bitmap){

    for($x=0;$x<strlen($bitmap);$x++){
    $mask=0x8;

    for($y=0;$y<4;$y++){
      if((($x * 4) + $y + 1) == $pos){
        if((hexdec(substr($bitmap,$x,1))&$mask) != 0){
          return True;
        }       
      }
       $mask = $mask >> 1;
    }

    }

}
max
  • 11
  • 2
0

I found also a solution for the second part may be no nice code but functional:

private function _setBitAtPosition($pos,$bitmap,$value){

if($this->_getBitAtPosition($pos,$bitmap) == $value){
    return $bitmap;
}

  $charpos = intval((($pos + 3) / 4 - 1));
  $bitpos = abs(($pos - ($charpos * 4)) - 4);
  $bitvalue = pow(2,$bitpos);

$fourbitvalue=hexdec(substr($bitmap,$charpos,1));

$newvalue = 0;

if($value){
    $newvalue = $fourbitvalue + $bitvalue;
} else {
    $newvalue = $fourbitvalue - $bitvalue;
}

$newbitmap = substr($bitmap,0,$charpos).dechex($newvalue).substr($bitmap,$charpos+1);

return $newbitmap;
}
max
  • 11
  • 2
0

Here is my perl function wich gives a list of bits position set with ranges. I'm using it do parse vlan membership bitmask, but it does not matter. For example:

# ./test.pl 6E
1-2,4-6

# ./test.pl FF
0-7

# ./test.pl 7fe7fffffe
1-10,13-38

Source:

sub vlans_list {
  my $raw=shift;
  my $cur_vlan=0;
  my $last_vlan=undef;
  my $seq_start=undef;
  my $list=undef;
  foreach my $octet (split('', $raw)) {
    $octet = hex($octet);
    for(my $i=0; $i < 4; $i++) {
      if($octet & 0x8) {
        if(defined($seq_start) && ($cur_vlan-$last_vlan) == 1) {
          $last_vlan=$cur_vlan;
        } elsif(!defined($seq_start)) {
          $seq_start=$cur_vlan;
          $last_vlan=$cur_vlan;
        } else {
          print("ERROR: vlans_list: sequencing error\n");
        };
      } else {
        if(defined($seq_start)) {
          if(defined($list)) {
            $list .= ",$seq_start";
          } else {
            $list = "$seq_start";
          };
          if($seq_start != $last_vlan) {
            $list .= "-$last_vlan";
          };
          $seq_start=undef;
          $last_vlan=undef;
        };
      };
      $cur_vlan++;
      $octet= $octet << 1;
    };
  };
  if(defined($seq_start)) {
    if(defined($list)) {
      $list .= ",$seq_start";
    } else {
      $list = "$seq_start";
    };
    if($seq_start != $last_vlan) {
      $list .= "-$last_vlan";
    };
  };
  if(!defined($list)) {
    $list="";
  };
  return $list;

};
Sergey
  • 344
  • 2
  • 12
  • Kudos. This works fine for finding the egress ports for a VLAN in Q-BRIDGE-MIB at .1.3.6.1.2.1.17.7.1.4.2.1.4. On our gear however I have to start counting ports at 1. (`my $cur_vlan=1`) – Marki Apr 04 '16 at 17:39